nx_dedither.nx source
↩ module page · 831 lines · 41866 B
1// nx_dedither.nx -- RECOVER A 1990s DITHERED IMAGE WITHOUT TOUCHING THE ORIGINAL BYTES.
2//
3// WHY THIS EXISTS (measured 2026-08-07, page3.com/13Nov96.gif): a 280x403 GIF weighing 81,953 B is a
4// PHOTOGRAPH crushed into a 256-entry palette. The encoder of 1996 traded colour depth for file size by
5// scattering alternating palette entries across smooth regions -- so a plain studio backdrop is stored as
6// high-frequency speckle. The archive serves those bytes FAITHFULLY, and faithful is exactly why the
7// backdrop reads as white fuzz. The fuzz is not our defect and not decode damage: header valid, trailer
8// 0x3B present, extension preserved 1:1 from the 1996 HTML, no re-encode anywhere in the pipeline.
9//
10// *THE ARCHIVE WAS RIGHT AND THE PICTURE STILL LOOKED WRONG. Those are different problems and only the
11// second one is fixable. Rule 25 says build intelligence, never strip features -- so this NEVER rewrites
12// the stored asset. It emits a SEPARATE enhanced render beside it. The original remains the record.
13//
14// HOW: a sigma filter (Lee 1983) -- average only over neighbours whose colour is already CLOSE to the
15// centre. Dither speckle is by construction a set of near-neighbours straddling the true value, so it
16// averages away; a real edge has far neighbours, which are EXCLUDED from the mean and therefore survive.
17// A plain box blur would also lower the noise metric -- and would destroy the picture. That is precisely
18// why the selftest below refuses to pass on noise reduction alone.
19//
20// RULER: mean absolute local deviation (MALD) vs a 3x3 mean, x1000, integer. Reported BEFORE and AFTER
21// so the claim is a measurement and not an adjective.
22//
23// usage: nx_dedither <in-image> <out.png> [radius=2] [threshold=40]
24// nx_dedither --kat (selftest: 4 teeth, 2 of them anti-vacuity)
25// argv[1]=input (any format nx_img_bytes_to_rgb decodes), argv[2]=output PNG.
26// exit 0 ok | 2 decode/write failure | 3 usage | 1 selftest RED
27// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
28import "nx_syscalls.nx"
29import "nx_img_to_rgb.nx"
30import "nx_png_write.nx"
31import "nx_img_resample.nx"
32
33// SCALE STAGE -- added 2026-08-07 on OCR EVIDENCE, not taste. A neutral OCR instrument
34// (Windows.Media.Ocr, an oracle in the qemu/openssl sense, never a runtime dep) read the archive's
35// prop.gif as "PropertyXET" at native 250x48; ground truth is "PropertyNET", fixed by the 1996 href
36// god.co.uk/propertynet/. At x2 and x3 the SAME instrument reads "PropertyNET" exactly; at x4 and x6 it
37// degrades again to "PropenyXET"/"PropenyNET" as the resampler fuses r+t into n. So the useful band is
38// MEASURED at x2-x3 with a real optimum, not assumed monotonic -- more upscale is NOT more legible.
39// *BICUBIC ON PURPOSE: the evidence above was produced with a bicubic resampler, so shipping bilinear
40// would be quoting a measurement taken with a different instrument than the one that runs.
41const DD_MAXR: i64 = 8
42const DD_MAXSCALE: i64 = 4
43// DITHER THRESHOLD -- CALIBRATED FROM A POPULATION, not from the two examples that inspired the feature.
44// `nx_dedither --census` over 78 real archive assets (JPEG photos, GIF logos, line art, and one known
45// heavily-dithered 1996 photograph) produced: bulk 212-405, then 457, then 549. The known-dithered photo
46// IS the corpus maximum, and the gap between 405 and 457 is the only real gap in the distribution.
47// 450 sits in that gap. This is an EMPIRICAL boundary for this corpus, not a physical constant --
48// it is quoted with the census that produced it precisely so a future seat can re-derive or move it.
49// CONFIRMATION LOOP (unplanned, and the strongest evidence here): running the filter on that photo drops
50// its altrate 549 -> 388, back into the bulk. The feature detects the property, the filter removes it,
51// and the feature then agrees it is gone -- measured on the same asset, both directions.
52// Erring permissive is CHEAP and deliberate: the sigma filter is measurably INERT on non-dithered art
53// (-22 permille on crisp line art), so a false positive costs disk, while a false negative leaves the
54// fuzz the operator actually complained about.
55const DD_DITHER_MIN: i64 = 450
56const DD_MAXTHR: i64 = 255
57
58func dp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
59func de(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 }
60func dnum(v: i64) -> i64 {
61 var m: i64 = v
62 if m < 0 { dp("-" as *u8); m = 0 - m }
63 let t: *u8 = sys_mmap(32)
64 var k: i64 = 0
65 if m == 0 { t[0] = 48 as u8; k = 1 }
66 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
67 let b: *u8 = sys_mmap(32)
68 var i: i64 = 0
69 while i < k { b[i] = t[k-1-i]; i = i + 1 }
70 sys_write(1, b, k)
71 return 0
72}
73func dd_atoi(s: *u8) -> i64 {
74 var v: i64 = 0
75 var i: i64 = 0
76 while s[i] != (0 as u8) {
77 let c: i64 = s[i] as i64
78 if c < 48 { return 0 - 1 }
79 if c > 57 { return 0 - 1 }
80 v = v * 10 + (c - 48)
81 i = i + 1
82 }
83 if i == 0 { return 0 - 1 }
84 return v
85}
86
87// MEAN ABSOLUTE LOCAL DEVIATION vs a 3x3 mean, x1000. Border pixels excluded (no clamped mean to bias it).
88// This is the dither ruler: speckle scores high, a smooth gradient scores near zero, and a hard edge also
89// scores high -- which is WHY the selftest cannot rely on this number alone.
90func dd_mald(rgb: *u8, w: i64, h: i64) -> i64 {
91 if w < 3 { return 0 }
92 if h < 3 { return 0 }
93 var acc: i64 = 0
94 var cnt: i64 = 0
95 var y: i64 = 1
96 while y < h - 1 {
97 var x: i64 = 1
98 while x < w - 1 {
99 var c: i64 = 0
100 while c < 3 {
101 var sum: i64 = 0
102 var yy: i64 = y - 1
103 while yy <= y + 1 {
104 var xx: i64 = x - 1
105 while xx <= x + 1 {
106 sum = sum + (rgb[(yy*w + xx)*3 + c] as i64)
107 xx = xx + 1
108 }
109 yy = yy + 1
110 }
111 var d: i64 = (rgb[(y*w + x)*3 + c] as i64) - (sum / 9)
112 if d < 0 { d = 0 - d }
113 acc = acc + d
114 cnt = cnt + 1
115 c = c + 1
116 }
117 x = x + 1
118 }
119 y = y + 1
120 }
121 if cnt == 0 { return 0 }
122 return (acc * 1000) / cnt
123}
124
125// LOCAL MEAN of the 3x3 window at (x,y) for channel c. Callers must keep 1 <= x < w-1, 1 <= y < h-1.
126func dd_localmean(rgb: *u8, w: i64, x: i64, y: i64, c: i64) -> i64 {
127 var sum: i64 = 0
128 var yy: i64 = y - 1
129 while yy <= y + 1 {
130 var xx: i64 = x - 1
131 while xx <= x + 1 {
132 sum = sum + (rgb[(yy*w + xx)*3 + c] as i64)
133 xx = xx + 1
134 }
135 yy = yy + 1
136 }
137 return sum / 9
138}
139
140// MEAN ABSOLUTE GRADIENT OF THE LOCAL-MEAN FIELD, x1000 -- the SECOND ruler, and the one that makes the
141// first one usable. MALD alone cannot identify dither: it reads high for palette speckle AND for genuine
142// text strokes (MEASURED -- the photo scored 6863 and a crisp logo scored 5062, and they need OPPOSITE
143// remedies). The discriminator is what the high frequency is sitting ON:
144// dither = high-frequency noise over a SMOOTH underlying mean -> MALD high, MEANGRAD low
145// edges = high frequency BECAUSE the underlying mean moves -> MALD high, MEANGRAD high
146// So the ratio separates them where either number alone cannot.
147// *A SINGLE STATISTIC THAT TWO OPPOSITE PHENOMENA BOTH MAXIMISE IS NOT A CLASSIFIER, IT IS A COINCIDENCE
148// DETECTOR -- it took a second, independent axis to tell them apart.
149func dd_meangrad(rgb: *u8, w: i64, h: i64) -> i64 {
150 if w < 4 { return 0 }
151 if h < 4 { return 0 }
152 var acc: i64 = 0
153 var cnt: i64 = 0
154 var y: i64 = 1
155 while y < h - 2 {
156 var x: i64 = 1
157 while x < w - 2 {
158 var c: i64 = 0
159 while c < 3 {
160 let m0: i64 = dd_localmean(rgb, w, x, y, c)
161 var dx: i64 = dd_localmean(rgb, w, x+1, y, c) - m0
162 if dx < 0 { dx = 0 - dx }
163 var dy: i64 = dd_localmean(rgb, w, x, y+1, c) - m0
164 if dy < 0 { dy = 0 - dy }
165 acc = acc + dx + dy
166 cnt = cnt + 1
167 c = c + 1
168 }
169 x = x + 1
170 }
171 y = y + 1
172 }
173 if cnt == 0 { return 0 }
174 return (acc * 1000) / cnt
175}
176
177// SIGN-ALTERNATION RATE, permille -- THE discriminator, after two weaker ones were measured and rejected.
178// MALD alone failed: it reads high for dither AND for text strokes (6863 photo vs 5062 logo).
179// MALD/meangrad failed too: only a 1.27x margin, and the photo's mean-gradient came out HIGHER than the
180// logo's because a photograph has real structure everywhere. Both were plausible and both were wrong.
181// *A FEATURE THAT MERELY CORRELATES WITH THE TARGET LOSES TO ONE DERIVED FROM ITS MECHANISM.
182// Dither is not just high-frequency -- it has a specific PHASE. Two palette entries approximate an
183// in-between value by alternating ABOVE and BELOW it on adjacent pixels, so the deviation-from-local-mean
184// FLIPS SIGN nearly every pixel (-> ~1000). Natural photographic texture has no phase discipline (~500 =
185// chance). A hard edge does not alternate at all. That is a property of how dithering WORKS, not a
186// statistic that happens to co-vary with it.
187// Flat regions are EXCLUDED (|deviation| < 2): they have no phase to measure, and counting their rounding
188// noise would drag every image toward chance and destroy the very separation this is for.
189func dd_altrate(rgb: *u8, w: i64, h: i64) -> i64 {
190 if w < 5 { return 0 }
191 if h < 5 { return 0 }
192 var flips: i64 = 0
193 var pairs: i64 = 0
194 var y: i64 = 1
195 while y < h - 1 {
196 var x: i64 = 1
197 while x < w - 2 {
198 var c: i64 = 0
199 while c < 3 {
200 let d0: i64 = (rgb[(y*w+x)*3+c] as i64) - dd_localmean(rgb, w, x, y, c)
201 let d1: i64 = (rgb[(y*w+x+1)*3+c] as i64) - dd_localmean(rgb, w, x+1, y, c)
202 var m0: i64 = d0
203 if m0 < 0 { m0 = 0 - m0 }
204 var m1: i64 = d1
205 if m1 < 0 { m1 = 0 - m1 }
206 var ok: i64 = 1
207 if m0 < 2 { ok = 0 }
208 if m1 < 2 { ok = 0 }
209 if ok == 1 {
210 pairs = pairs + 1
211 var flip: i64 = 0
212 if d0 > 0 { if d1 < 0 { flip = 1 } }
213 if d0 < 0 { if d1 > 0 { flip = 1 } }
214 flips = flips + flip
215 }
216 c = c + 1
217 }
218 x = x + 1
219 }
220 y = y + 1
221 }
222 if pairs == 0 { return 0 }
223 return (flips * 1000) / pairs
224}
225
226// SIGMA FILTER. Window bounds are clamped BEFORE the inner loops so the hot path carries no nested
227// bounds tests -- flat ifs on purpose (a 4-deep nested if is a known nx_cc landmine).
228func dd_sigma(src: *u8, dst: *u8, w: i64, h: i64, r: i64, thr: i64) -> i64 {
229 var y: i64 = 0
230 while y < h {
231 var x: i64 = 0
232 while x < w {
233 let po: i64 = (y*w + x)*3
234 let pr: i64 = src[po] as i64
235 let pg: i64 = src[po+1] as i64
236 let pb: i64 = src[po+2] as i64
237 var y0: i64 = y - r
238 if y0 < 0 { y0 = 0 }
239 var y1: i64 = y + r
240 if y1 > h - 1 { y1 = h - 1 }
241 var x0: i64 = x - r
242 if x0 < 0 { x0 = 0 }
243 var x1: i64 = x + r
244 if x1 > w - 1 { x1 = w - 1 }
245 var sr: i64 = 0
246 var sg: i64 = 0
247 var sb: i64 = 0
248 var n: i64 = 0
249 var yy: i64 = y0
250 while yy <= y1 {
251 var xx: i64 = x0
252 while xx <= x1 {
253 let qo: i64 = (yy*w + xx)*3
254 let qr: i64 = src[qo] as i64
255 let qg: i64 = src[qo+1] as i64
256 let qb: i64 = src[qo+2] as i64
257 var da: i64 = qr - pr
258 if da < 0 { da = 0 - da }
259 var db: i64 = qg - pg
260 if db < 0 { db = 0 - db }
261 var dc: i64 = qb - pb
262 if dc < 0 { dc = 0 - dc }
263 // THRESHOLD IS THE PER-CHANNEL MEAN, NOT THE 3-CHANNEL SUM. The sum form shipped first
264 // and T2 caught it immediately: a grey dither of 120 vs 136 is 16 PER CHANNEL but 48
265 // SUMMED, so a threshold of 40 excluded the very speckle the filter exists to average --
266 // the organ ran, reported success, and changed nothing. Comparing against thr*3 keeps the
267 // arithmetic exact (no divide, no rounding) while letting the operator think in 0-255
268 // levels, which is the only unit a threshold on 8-bit colour can honestly be quoted in.
269 if da + db + dc <= thr * 3 { sr = sr + qr; sg = sg + qg; sb = sb + qb; n = n + 1 }
270 xx = xx + 1
271 }
272 yy = yy + 1
273 }
274 if n == 0 { sr = pr; sg = pg; sb = pb; n = 1 }
275 dst[po] = (sr/n) as u8
276 dst[po+1] = (sg/n) as u8
277 dst[po+2] = (sb/n) as u8
278 x = x + 1
279 }
280 y = y + 1
281 }
282 return 0
283}
284
285// mean absolute difference between column xa and column xb (edge-contrast probe)
286func dd_coldiff(rgb: *u8, w: i64, h: i64, xa: i64, xb: i64) -> i64 {
287 var acc: i64 = 0
288 var cnt: i64 = 0
289 var y: i64 = 0
290 while y < h {
291 var c: i64 = 0
292 while c < 3 {
293 var d: i64 = (rgb[(y*w + xa)*3 + c] as i64) - (rgb[(y*w + xb)*3 + c] as i64)
294 if d < 0 { d = 0 - d }
295 acc = acc + d
296 cnt = cnt + 1
297 c = c + 1
298 }
299 y = y + 1
300 }
301 if cnt == 0 { return 0 }
302 return acc / cnt
303}
304
305func dd_kat() -> i64 {
306 let w: i64 = 64
307 let h: i64 = 64
308 let a: *u8 = sys_mmap(w*h*3 + 16)
309 let b: *u8 = sys_mmap(w*h*3 + 16)
310 var pass: i64 = 0
311 var total: i64 = 0
312
313 // ---- fixture 1: a DITHERED flat field. Two palette entries (120 and 136) alternating on a
314 // checkerboard -- the exact structure a 1996 encoder produces for a smooth mid-grey backdrop.
315 var y: i64 = 0
316 while y < h {
317 var x: i64 = 0
318 while x < w {
319 var v: i64 = 120
320 if (x + y) % 2 == 0 { v = 136 }
321 let o: i64 = (y*w + x)*3
322 a[o] = v as u8; a[o+1] = v as u8; a[o+2] = v as u8
323 x = x + 1
324 }
325 y = y + 1
326 }
327 let m0: i64 = dd_mald(a, w, h)
328 dd_sigma(a, b, w, h, 2, 40)
329 let m1: i64 = dd_mald(b, w, h)
330 total = total + 1
331 if m0 > 3000 { pass = pass + 1; dp("T1 GREEN dither fixture registers on the ruler (mald=" as *u8); dnum(m0); dp(")\n" as *u8) } else { dp("T1 RED fixture did not register (mald=" as *u8); dnum(m0); dp(")\n" as *u8) }
332 total = total + 1
333 if m1 * 2 < m0 { pass = pass + 1; dp("T2 GREEN dither removed >50pct (" as *u8); dnum(m0); dp(" -> " as *u8); dnum(m1); dp(")\n" as *u8) } else { dp("T2 RED dither NOT removed (" as *u8); dnum(m0); dp(" -> " as *u8); dnum(m1); dp(")\n" as *u8) }
334
335 // ---- fixture 2: ANTI-VACUITY. A hard vertical edge, black|white at x=32. A box blur would smear
336 // this and still score well on T2, so T3 is the tooth that a mere blur CANNOT pass.
337 var y2: i64 = 0
338 while y2 < h {
339 var x2: i64 = 0
340 while x2 < w {
341 var v2: i64 = 0
342 if x2 >= 32 { v2 = 255 }
343 let o2: i64 = (y2*w + x2)*3
344 a[o2] = v2 as u8; a[o2+1] = v2 as u8; a[o2+2] = v2 as u8
345 x2 = x2 + 1
346 }
347 y2 = y2 + 1
348 }
349 let e0: i64 = dd_coldiff(a, w, h, 31, 32)
350 dd_sigma(a, b, w, h, 2, 40)
351 let e1: i64 = dd_coldiff(b, w, h, 31, 32)
352 total = total + 1
353 if e1 * 10 >= e0 * 9 { pass = pass + 1; dp("T3 GREEN edge PRESERVED (" as *u8); dnum(e0); dp(" -> " as *u8); dnum(e1); dp(") -- a box blur cannot pass this\n" as *u8) } else { dp("T3 RED edge was smeared (" as *u8); dnum(e0); dp(" -> " as *u8); dnum(e1); dp(")\n" as *u8) }
354
355 // ---- fixture 3: ANTI-VACUITY. An ALREADY-CLEAN flat field must come out unchanged: a filter that
356 // invents texture on smooth input would be worse than the disease.
357 var y3: i64 = 0
358 while y3 < h {
359 var x3: i64 = 0
360 while x3 < w {
361 let o3: i64 = (y3*w + x3)*3
362 a[o3] = 128 as u8; a[o3+1] = 128 as u8; a[o3+2] = 128 as u8
363 x3 = x3 + 1
364 }
365 y3 = y3 + 1
366 }
367 dd_sigma(a, b, w, h, 2, 40)
368 var flat: i64 = 1
369 var i3: i64 = 0
370 while i3 < w*h*3 { if b[i3] != (128 as u8) { flat = 0; i3 = w*h*3 } else { i3 = i3 + 1 } }
371 total = total + 1
372 if flat == 1 { pass = pass + 1; dp("T4 GREEN clean input unchanged (no invented texture)\n" as *u8) } else { dp("T4 RED filter altered an already-clean field\n" as *u8) }
373
374 // ---- T5/T6: the PHASE discriminator, with a control that isolates phase and NOTHING else.
375 // Both fixtures use the SAME two palette entries (120/136) and therefore the same amplitude and
376 // nearly the same MALD. They differ ONLY in phase: T5 alternates every pixel (real dither), T6 uses
377 // 2x2 blocks (same colours, same contrast, no per-pixel alternation). If altrate could be fooled by
378 // amplitude or palette size it would score these two alike -- so T6 is what makes T5 mean something.
379 var y5: i64 = 0
380 while y5 < h {
381 var x5: i64 = 0
382 while x5 < w {
383 var v5: i64 = 120
384 if (x5 + y5) % 2 == 0 { v5 = 136 }
385 let o5: i64 = (y5*w + x5)*3
386 a[o5] = v5 as u8; a[o5+1] = v5 as u8; a[o5+2] = v5 as u8
387 var v6: i64 = 120
388 if ((x5/2) + (y5/2)) % 2 == 0 { v6 = 136 }
389 let o6: i64 = (y5*w + x5)*3
390 b[o6] = v6 as u8; b[o6+1] = v6 as u8; b[o6+2] = v6 as u8
391 x5 = x5 + 1
392 }
393 y5 = y5 + 1
394 }
395 let ar_dith: i64 = dd_altrate(a, w, h)
396 let ar_blok: i64 = dd_altrate(b, w, h)
397 total = total + 1
398 if ar_dith >= 900 { pass = pass + 1; dp("T5 GREEN per-pixel dither has dither PHASE (altrate=" as *u8); dnum(ar_dith); dp("/1000)\n" as *u8) } else { dp("T5 RED dither phase not detected (altrate=" as *u8); dnum(ar_dith); dp(")\n" as *u8) }
399 total = total + 1
400 if ar_blok + 200 < ar_dith { pass = pass + 1; dp("T6 GREEN 2x2 blocks SAME colours REJECTED on phase (" as *u8); dnum(ar_blok); dp(" vs " as *u8); dnum(ar_dith); dp(") -- amplitude alone cannot pass\n" as *u8) } else { dp("T6 RED phase control not separated (" as *u8); dnum(ar_blok); dp(" vs " as *u8); dnum(ar_dith); dp(")\n" as *u8) }
401
402 // ---- T7: SELECTIVITY WITH BOTH SIGNALS PRESENT AT ONCE.
403 // T2 proves noise falls on a pure-dither fixture; T3 proves an edge survives on a pure-edge fixture.
404 // Neither proves the filter can tell them apart WHEN THEY OVERLAP, which is the only case a real
405 // photograph ever presents. This fixture is a hard edge (60|200) with per-pixel dither laid over
406 // BOTH sides, and it demands the two outcomes SIMULTANEOUSLY: the speckle goes and the edge stays.
407 // A filter that passed T2 and T3 separately can still fail here by smearing the edge wherever noise
408 // sits on it -- and an image is nothing but edges with noise sitting on them.
409 var y7: i64 = 0
410 while y7 < h {
411 var x7: i64 = 0
412 while x7 < w {
413 var base: i64 = 60
414 if x7 >= 32 { base = 200 }
415 var v7: i64 = base - 8
416 if (x7 + y7) % 2 == 0 { v7 = base + 8 }
417 let o7: i64 = (y7*w + x7)*3
418 a[o7] = v7 as u8; a[o7+1] = v7 as u8; a[o7+2] = v7 as u8
419 x7 = x7 + 1
420 }
421 y7 = y7 + 1
422 }
423 let n7a: i64 = dd_mald(a, w, h)
424 let e7a: i64 = dd_coldiff(a, w, h, 20, 44)
425 dd_sigma(a, b, w, h, 2, 40)
426 let n7b: i64 = dd_mald(b, w, h)
427 let e7b: i64 = dd_coldiff(b, w, h, 20, 44)
428 total = total + 1
429 var sel: i64 = 0
430 if n7b * 2 < n7a { if e7b * 10 >= e7a * 9 { sel = 1 } }
431 if sel == 1 { pass = pass + 1; dp("T7 GREEN SELECTIVE with both present: noise " as *u8); dnum(n7a); dp("->" as *u8); dnum(n7b); dp(" while edge " as *u8); dnum(e7a); dp("->" as *u8); dnum(e7b); dp(" held\n" as *u8) } else { dp("T7 RED not selective: noise " as *u8); dnum(n7a); dp("->" as *u8); dnum(n7b); dp(" edge " as *u8); dnum(e7a); dp("->" as *u8); dnum(e7b); dp("\n" as *u8) }
432
433 dp("nx_dedither KAT " as *u8); dnum(pass); dp("/" as *u8); dnum(total); dp("\n" as *u8)
434 if pass == total { return 0 }
435 return 1
436}
437
438// CLASSIFY: report both rulers + their ratio for one image. NO VERDICT IS PRINTED YET, ON PURPOSE.
439// A threshold separating DITHERED from CLEAN has not been MEASURED, and a constant invented at authoring
440// time would be indistinguishable in the output from one derived from evidence -- which is precisely the
441// failure this organ already committed once (a threshold whose unit nobody had stated).
442// *AN UNCALIBRATED CLASSIFIER MUST REPORT NUMBERS, NEVER VERDICTS: a verdict claims a decision boundary
443// exists; numbers only claim what was observed. Calibrate against known assets, THEN earn the verdict.
444func dd_classify(path: *u8) -> i64 {
445 let wh: *i64 = sys_mmap(32) as *i64
446 let rgb: *u8 = nx_img_to_rgb(path, wh)
447 if rgb == (0 as *u8) { de("nx_dedither: UNDECODABLE\n" as *u8); return 2 }
448 let w: i64 = wh[0]
449 let h: i64 = wh[1]
450 if w < 4 { de("nx_dedither: image too small to classify\n" as *u8); return 2 }
451 if h < 4 { de("nx_dedither: image too small to classify\n" as *u8); return 2 }
452 let mald: i64 = dd_mald(rgb, w, h)
453 let mg: i64 = dd_meangrad(rgb, w, h)
454 let ratio: i64 = (mald * 1000) / (mg + 1)
455 dp("{\"organ\":\"nx_dedither\",\"mode\":\"classify\",\"w\":" as *u8); dnum(w)
456 dp(",\"h\":" as *u8); dnum(h)
457 dp(",\"mald_x1000\":" as *u8); dnum(mald)
458 dp(",\"meangrad_x1000\":" as *u8); dnum(mg)
459 dp(",\"dither_ratio_x1000\":" as *u8); dnum(ratio)
460 let ar: i64 = dd_altrate(rgb, w, h)
461 let pal: i64 = dd_is_palette(path)
462 dp(",\"altrate_permil\":" as *u8); dnum(ar)
463 dp(",\"palette_format\":" as *u8); dnum(pal)
464 dp(",\"threshold\":" as *u8); dnum(DD_DITHER_MIN)
465 // The verdict is now EARNED: the boundary came from an 78-asset census, and it is printed alongside
466 // the number and the threshold so a reader can always re-judge it rather than take the word for it.
467 var vd: i64 = 1
468 if ar < DD_DITHER_MIN { vd = 0 }
469 if pal == 0 { vd = 0 }
470 if vd == 1 { dp(",\"verdict\":\"DITHERED\"}\n" as *u8) }
471 if vd == 0 { if pal == 0 { dp(",\"verdict\":\"NON-PALETTE\"}\n" as *u8) } else { dp(",\"verdict\":\"CLEAN\"}\n" as *u8) } }
472 return 0
473}
474
475// ---- CENSUS ----------------------------------------------------------------------------------
476// WHY THIS EXISTS: two real samples is not a calibration. Classifying the archive one file per
477// invocation cannot produce a DISTRIBUTION, and without a distribution any threshold is an invented
478// constant wearing a measurement's clothes -- the exact failure this organ already committed once.
479// *A CLASSIFIER IS CALIBRATED BY A POPULATION, NOT BY THE TWO EXAMPLES THAT INSPIRED IT.
480// BOUNDED BY CONSTRUCTION (the nx_gate_build_sweep idiom): maxn is REQUIRED and must be > 0, so a
481// census can never run away over a corpus of unknown size.
482// Undecodable entries print SKIP with a reason rather than vanishing -- a census that silently drops
483// what it could not read reports a cleaner corpus than exists.
484const DD_DIRBUF: i64 = 262144
485const DD_RECLEN_OFF: i64 = 16
486const DD_NAME_OFF: i64 = 19
487
488func dd_cat(dst: *u8, off: i64, src: *u8) -> i64 { var o: i64=off; var j: i64=0; while src[j]!=(0 as u8) { dst[o]=src[j]; o=o+1; j=j+1 } return o }
489
490func dd_census(dir: *u8, maxn: i64) -> i64 {
491 if maxn <= 0 { de("nx_dedither: --census REFUSES an unbounded run; pass maxfiles > 0\n" as *u8); return 3 }
492 let fd: i64 = sys_openat_rd(dir)
493 if fd < 0 { de("nx_dedither: cannot open directory\n" as *u8); return 2 }
494 let db: *u8 = sys_mmap(DD_DIRBUF)
495 dp("# altrate mald meangrad w h name\n" as *u8)
496 let path: *u8 = sys_mmap(1024)
497 let wh: *i64 = sys_mmap(32) as *i64
498 var shown: i64 = 0
499 // Same getdents64 batching contract as dd_sweep -- see the note there. Fixed in BOTH, because a
500 // census and a sweep that disagree about how much of a directory exists is worse than either bug alone.
501 var batches: i64 = 0
502 var go: i64 = 1
503 while go == 1 {
504 let n: i64 = sys_getdents64(fd, db, DD_DIRBUF)
505 if n <= 0 { go = 0 } else {
506 batches = batches + 1
507 var p: i64 = 0
508 while p < n {
509 let reclen: i64 = (db[p+DD_RECLEN_OFF] as i64) | ((db[p+DD_RECLEN_OFF+1] as i64) << 8)
510 if reclen <= 0 { p = n } else {
511 let nm: i64 = p + DD_NAME_OFF
512 var skip: i64 = 0
513 if (db[nm] as i64) == 46 { skip = 1 }
514 if shown >= maxn { skip = 1 }
515 if skip == 0 {
516 var o: i64 = dd_cat(path, 0, dir)
517 path[o] = 47 as u8; o = o + 1
518 var w2: i64 = nm
519 while db[w2] != (0 as u8) { path[o]=db[w2]; o=o+1; w2=w2+1 }
520 path[o] = 0 as u8
521 let rgb: *u8 = nx_img_to_rgb(path, wh)
522 if rgb == (0 as *u8) {
523 dp("SKIP undecodable " as *u8)
524 var w3: i64 = nm
525 while db[w3] != (0 as u8) { sys_write(1, ((db as i64)+w3) as *u8, 1); w3=w3+1 }
526 dp("\n" as *u8)
527 } else {
528 let iw: i64 = wh[0]
529 let ih: i64 = wh[1]
530 dnum(dd_altrate(rgb, iw, ih)); dp(" " as *u8)
531 dnum(dd_mald(rgb, iw, ih)); dp(" " as *u8)
532 dnum(dd_meangrad(rgb, iw, ih)); dp(" " as *u8)
533 dnum(iw); dp(" " as *u8); dnum(ih); dp(" " as *u8)
534 var w4: i64 = nm
535 while db[w4] != (0 as u8) { sys_write(1, ((db as i64)+w4) as *u8, 1); w4=w4+1 }
536 dp("\n" as *u8)
537 }
538 shown = shown + 1
539 }
540 p = p + reclen
541 }
542 }
543 }
544 }
545 sys_close(fd)
546 if batches == 0 { de("nx_dedither: not a directory (getdents64 refused)\n" as *u8); return 2 }
547 dp("# census rows=" as *u8); dnum(shown); dp("\n" as *u8)
548 return 0
549}
550
551// ---- FORMAT PRIOR ------------------------------------------------------------------------------
552// MEASURED REFUTATION (2026-08-07): the 450 threshold was calibrated on page3.com (78 assets, bulk
553// topped out at 405, the two true positives BOTH .gif). Run against megastar.co.uk it collapsed --
554// small heavily-compressed JPEGs score 447/468/476/483/503/509/511 routinely. A threshold that
555// separates one corpus and misfires on the next is not a classifier, it is a fitted constant.
556// *A BOUNDARY CALIBRATED ON ONE POPULATION MUST BE RE-TESTED ON A SECOND BEFORE IT IS BELIEVED --
557// the second corpus is where a fit stops being evidence and starts being a coincidence.
558// The fix is a PRIOR FROM THE MECHANISM, not a retuned number: palette dithering is something an
559// INDEXED format does -- approximating an unavailable colour by alternating two palette entries.
560// JPEG has no palette at all (DCT coefficients), so whatever raises its alternation score is ringing
561// and blocking, which a sigma filter is the wrong remedy for anyway. Gating on the container removes
562// every observed false positive by construction and cannot be tuned away by a future corpus.
563// Sniffed from MAGIC BYTES, never the extension -- .gif files that are secretly JPEG are exactly the
564// kind of thing an archive is full of, and the extension is a claim while the header is evidence.
565func dd_is_palette(path: *u8) -> i64 {
566 let fd: i64 = sys_openat_rd(path)
567 if fd < 0 { return 0 }
568 let b: *u8 = sys_mmap(16)
569 let n: i64 = sys_read(fd, b, 8)
570 sys_close(fd)
571 if n < 4 { return 0 }
572 // GIF87a / GIF89a -- the dominant 1990s palette container
573 var g: i64 = 1
574 if (b[0] as i64) != 71 { g = 0 }
575 if (b[1] as i64) != 73 { g = 0 }
576 if (b[2] as i64) != 70 { g = 0 }
577 if g == 1 { return 1 }
578 // BMP ("BM") -- indexed at 1/4/8bpp; truecolour BMPs simply will not score as dithered
579 var m: i64 = 1
580 if (b[0] as i64) != 66 { m = 0 }
581 if (b[1] as i64) != 77 { m = 0 }
582 if m == 1 { return 1 }
583 // PCX (0x0A) -- era palette format
584 if (b[0] as i64) == 10 { return 1 }
585 return 0
586}
587
588// does name end with sfx?
589func dd_endswith(nm: *u8, sfx: *u8) -> i64 {
590 var ln: i64 = 0
591 while nm[ln] != (0 as u8) { ln = ln + 1 }
592 var ls: i64 = 0
593 while sfx[ls] != (0 as u8) { ls = ls + 1 }
594 if ln < ls { return 0 }
595 var i: i64 = 0
596 while i < ls {
597 if nm[ln-ls+i] != sfx[i] { return 0 }
598 i = i + 1
599 }
600 return 1
601}
602
603// ---- SWEEP -------------------------------------------------------------------------------------
604// Enhance ONLY what the census says needs it. Blanket enhancement was measured to be waste: the sigma
605// filter moves crisp line art by -22 permille, so re-encoding 78 logos to "fix" them buys nothing and
606// costs disk. The classifier decides per asset, and the DECISION IS PRINTED for every file either way --
607// a sweep that logs only what it changed cannot be audited for what it silently skipped.
608// IDEMPOTENT (rule 10): outputs are skipped by suffix, so a second run over the same directory is a
609// no-op rather than a cascade of .enh.enh.png. THE ORIGINAL IS NEVER WRITTEN.
610func dd_sweep(dir: *u8, maxn: i64, r: i64, thr: i64, scale: i64) -> i64 {
611 if maxn <= 0 { de("nx_dedither: --sweep REFUSES an unbounded run; pass maxfiles > 0\n" as *u8); return 3 }
612 let fd: i64 = sys_openat_rd(dir)
613 if fd < 0 { de("nx_dedither: cannot open directory\n" as *u8); return 2 }
614 let db: *u8 = sys_mmap(DD_DIRBUF)
615 let inp: *u8 = sys_mmap(1024)
616 let outp: *u8 = sys_mmap(1024)
617 let wh: *i64 = sys_mmap(32) as *i64
618 var seen: i64 = 0
619 var enh: i64 = 0
620 var clean: i64 = 0
621 var nonpal: i64 = 0
622 var bad: i64 = 0
623 // *ONE getdents64 CALL IS NOT A DIRECTORY LISTING. The kernel returns as many entries as fit the
624 // buffer and expects to be called again until it answers 0. A single call happened to cover both
625 // archive dirs (69 and 77 entries) ONLY because they are small -- on a corpus large enough to matter
626 // this would have processed a PREFIX and then printed a confident total for it. That is precisely the
627 // failure this organ warns about two functions up: a census that drops what it did not read reports a
628 // cleaner corpus than exists. It passed its first two real runs by luck, which is the worst way to
629 // pass. Loop until the kernel says stop, and keep the fd open across calls.
630 var batches: i64 = 0
631 var go: i64 = 1
632 while go == 1 {
633 let n: i64 = sys_getdents64(fd, db, DD_DIRBUF)
634 if n <= 0 { go = 0 } else {
635 batches = batches + 1
636 var p: i64 = 0
637 while p < n {
638 let reclen: i64 = (db[p+DD_RECLEN_OFF] as i64) | ((db[p+DD_RECLEN_OFF+1] as i64) << 8)
639 if reclen <= 0 { p = n } else {
640 let nmo: i64 = p + DD_NAME_OFF
641 let nm: *u8 = ((db as i64) + nmo) as *u8
642 var skip: i64 = 0
643 if (nm[0] as i64) == 46 { skip = 1 }
644 if dd_endswith(nm, ".enh.png" as *u8) == 1 { skip = 1 }
645 if seen >= maxn { skip = 1 }
646 if skip == 0 {
647 seen = seen + 1
648 var io: i64 = dd_cat(inp, 0, dir)
649 inp[io] = 47 as u8; io = io + 1
650 io = dd_cat(inp, io, nm)
651 inp[io] = 0 as u8
652 let rgb: *u8 = nx_img_to_rgb(inp, wh)
653 if rgb == (0 as *u8) {
654 bad = bad + 1
655 dp("SKIP-UNDECODABLE " as *u8); dp(nm); dp("\n" as *u8)
656 } else {
657 let iw: i64 = wh[0]
658 let ih: i64 = wh[1]
659 let ar: i64 = dd_altrate(rgb, iw, ih)
660 let pal: i64 = dd_is_palette(inp)
661 var doit: i64 = 1
662 if ar < DD_DITHER_MIN { doit = 0 }
663 if pal == 0 { doit = 0 }
664 if doit == 0 {
665 // COUNT THE TWO CAUSES SEPARATELY. The per-line log already names which reason
666 // applied, but the SUMMARY collapsed both into "skipped_clean" -- so a run that
667 // rejected 60 JPEGs on format read as though it had inspected 60 clean assets and
668 // found them fine. A total that merges two causes is a total that cannot be acted on.
669 if pal == 0 { nonpal = nonpal + 1 } else { clean = clean + 1 }
670 // NAME WHICH REASON. "Skipped" without a cause is unauditable, and these two have
671 // opposite remedies: a low score means the asset is genuinely fine, a non-palette
672 // container means this organ is simply the wrong tool for whatever it does have.
673 if pal == 0 { dp("SKIP-NONPALETTE altrate=" as *u8) } else { dp("SKIP-CLEAN altrate=" as *u8) }
674 dnum(ar); dp(" " as *u8); dp(nm); dp("\n" as *u8)
675 } else {
676 let before: i64 = dd_mald(rgb, iw, ih)
677 let dst: *u8 = sys_mmap(iw*ih*3 + 16)
678 dd_sigma(rgb, dst, iw, ih, r, thr)
679 let after: i64 = dd_mald(dst, iw, ih)
680 var ow: i64 = iw
681 var oh: i64 = ih
682 var fin: *u8 = dst
683 if scale > 1 {
684 ow = iw * scale
685 oh = ih * scale
686 fin = sys_mmap(ow*oh*3 + 16)
687 nx_img_scale_bicubic(dst, iw, ih, 3, fin, ow, oh)
688 }
689 var oo: i64 = dd_cat(outp, 0, dir)
690 outp[oo] = 47 as u8; oo = oo + 1
691 oo = dd_cat(outp, oo, nm)
692 oo = dd_cat(outp, oo, ".enh.png" as *u8)
693 outp[oo] = 0 as u8
694 if nx_png_write_rgb(outp, fin, ow, oh) != 0 {
695 bad = bad + 1
696 dp("WRITE-FAILED " as *u8); dp(nm); dp("\n" as *u8)
697 } else {
698 enh = enh + 1
699 dp("ENHANCED altrate=" as *u8); dnum(ar)
700 dp(" mald " as *u8); dnum(before); dp("->" as *u8); dnum(after)
701 dp(" out " as *u8); dnum(ow); dp("x" as *u8); dnum(oh)
702 dp(" " as *u8); dp(nm); dp(".enh.png\n" as *u8)
703 }
704 }
705 }
706 }
707 p = p + reclen
708 }
709 }
710 }
711 }
712 sys_close(fd)
713 if batches == 0 { de("nx_dedither: not a directory (getdents64 refused)\n" as *u8); return 2 }
714 dp("# sweep seen=" as *u8); dnum(seen)
715 dp(" enhanced=" as *u8); dnum(enh)
716 dp(" skipped_clean=" as *u8); dnum(clean)
717 dp(" skipped_nonpalette=" as *u8); dnum(nonpal)
718 dp(" undecodable=" as *u8); dnum(bad)
719 dp(" threshold=" as *u8); dnum(DD_DITHER_MIN)
720 dp("\n" as *u8)
721 return 0
722}
723
724func main(argc: i64, argv: *i64) -> i64 {
725 if argc < 2 { de("usage: nx_dedither <in-image> <out.png> [radius=2] [threshold=40] | --kat\n" as *u8); sys_exit(3); return 3 }
726 let a1: *u8 = argv[1] as *u8
727 if a1[0] == (45 as u8) {
728 if a1[2] == (107 as u8) { let rc: i64 = dd_kat(); sys_exit(rc); return rc }
729 if a1[2] == (99 as u8) {
730 if argc < 3 { de("usage: nx_dedither --classify <image> | --census <dir> <maxfiles>\n" as *u8); sys_exit(3); return 3 }
731 // --classify and --census both begin "--c"; the 4th char disambiguates ('l' vs 'e').
732 if a1[3] == (101 as u8) {
733 var mx: i64 = 0
734 if argc >= 4 { mx = dd_atoi(argv[3] as *u8) }
735 let rc3: i64 = dd_census(argv[2] as *u8, mx)
736 sys_exit(rc3); return rc3
737 }
738 let rc2: i64 = dd_classify(argv[2] as *u8)
739 sys_exit(rc2); return rc2
740 }
741 if a1[2] == (115 as u8) {
742 if argc < 4 { de("usage: nx_dedither --sweep <dir> <maxfiles> [radius=2] [threshold=40] [scale=1]\n" as *u8); sys_exit(3); return 3 }
743 var smx: i64 = dd_atoi(argv[3] as *u8)
744 var sr: i64 = 2
745 var sthr: i64 = 40
746 var ssc: i64 = 1
747 if argc >= 5 { sr = dd_atoi(argv[4] as *u8) }
748 if argc >= 6 { sthr = dd_atoi(argv[5] as *u8) }
749 if argc >= 7 { ssc = dd_atoi(argv[6] as *u8) }
750 if sr < 0 { de("nx_dedither: REFUSED bad radius\n" as *u8); sys_exit(3); return 3 }
751 if sr > DD_MAXR { de("nx_dedither: REFUSED radius > 8\n" as *u8); sys_exit(3); return 3 }
752 if ssc < 1 { de("nx_dedither: REFUSED scale < 1\n" as *u8); sys_exit(3); return 3 }
753 if ssc > DD_MAXSCALE { de("nx_dedither: REFUSED scale > 4 (OCR-measured optimum is x2-x3)\n" as *u8); sys_exit(3); return 3 }
754 let rc4: i64 = dd_sweep(argv[2] as *u8, smx, sr, sthr, ssc)
755 sys_exit(rc4); return rc4
756 }
757 de("nx_dedither: unknown flag (--kat | --classify <image> | --census <dir> <n> | --sweep <dir> <n>)\n" as *u8); sys_exit(3); return 3
758 }
759 if argc < 3 { de("usage: nx_dedither <in-image> <out.png> [radius=2] [threshold=40]\n" as *u8); sys_exit(3); return 3 }
760 let outp: *u8 = argv[2] as *u8
761 var r: i64 = 2
762 var thr: i64 = 40
763 if argc >= 4 { r = dd_atoi(argv[3] as *u8) }
764 if argc >= 5 { thr = dd_atoi(argv[4] as *u8) }
765 // REFUSE nonsense rather than clamp silently: a caller who typed a bad radius wants to know.
766 if r < 0 { de("nx_dedither: REFUSED bad radius\n" as *u8); sys_exit(3); return 3 }
767 if r > DD_MAXR { de("nx_dedither: REFUSED radius > 8\n" as *u8); sys_exit(3); return 3 }
768 if thr < 0 { de("nx_dedither: REFUSED bad threshold\n" as *u8); sys_exit(3); return 3 }
769 if thr > DD_MAXTHR { de("nx_dedither: REFUSED threshold > 255 (it is a per-channel level, 0-255)\n" as *u8); sys_exit(3); return 3 }
770 var scale: i64 = 1
771 if argc >= 6 { scale = dd_atoi(argv[5] as *u8) }
772 if scale < 1 { de("nx_dedither: REFUSED scale < 1\n" as *u8); sys_exit(3); return 3 }
773 // REFUSE past the MEASURED band rather than silently obeying. x4 and x6 were both tested and both
774 // read WORSE than x3 on the OCR instrument, so a caller asking for x8 is asking for a degradation
775 // this organ has already measured. The ceiling is evidence, not caution.
776 if scale > DD_MAXSCALE { de("nx_dedither: REFUSED scale > 4 (OCR-measured optimum is x2-x3; x4+ degrades)\n" as *u8); sys_exit(3); return 3 }
777
778 let wh: *i64 = sys_mmap(32) as *i64
779 let src: *u8 = nx_img_to_rgb(a1, wh)
780 if src == (0 as *u8) { de("nx_dedither: UNDECODABLE (format unsupported or file unreadable)\n" as *u8); sys_exit(2); return 2 }
781 let w: i64 = wh[0]
782 let h: i64 = wh[1]
783 if w <= 0 { de("nx_dedither: bad width\n" as *u8); sys_exit(2); return 2 }
784 if h <= 0 { de("nx_dedither: bad height\n" as *u8); sys_exit(2); return 2 }
785
786 let before: i64 = dd_mald(src, w, h)
787 let dst: *u8 = sys_mmap(w*h*3 + 16)
788 dd_sigma(src, dst, w, h, r, thr)
789 // MALD is measured on the FILTERED pixels at NATIVE resolution, before any upscale. Measuring it
790 // after resampling would score the resampler's own smoothing as if the filter had earned it.
791 let after: i64 = dd_mald(dst, w, h)
792 // *NOISE REDUCTION ALONE IS NOT A QUALITY MEASURE -- A FILTER THAT DESTROYS THE PICTURE SCORES
793 // PERFECTLY ON IT. Reporting one number invites exactly the conclusion the number cannot support.
794 // The second axis is the mean-gradient of the local-mean field: it tracks real STRUCTURE (edges,
795 // features), which a selective filter must LEAVE ALONE while it removes speckle. Measured on the
796 // 1996 photo the two move at very different rates -- noise falls to 38 percent while structure holds
797 // at 82 -- and that GAP, not the reduction, is what says the filter is selective rather than a blur.
798 // Quoted together so the trade-off is visible at the point of decision instead of inferred later.
799 let mg_before: i64 = dd_meangrad(src, w, h)
800 let mg_after: i64 = dd_meangrad(dst, w, h)
801 var ow: i64 = w
802 var oh: i64 = h
803 var final: *u8 = dst
804 if scale > 1 {
805 ow = w * scale
806 oh = h * scale
807 final = sys_mmap(ow*oh*3 + 16)
808 if nx_img_scale_bicubic(dst, w, h, 3, final, ow, oh) != 0 { de("nx_dedither: SCALE FAILED\n" as *u8); sys_exit(2); return 2 }
809 }
810 if nx_png_write_rgb(outp, final, ow, oh) != 0 { de("nx_dedither: PNG WRITE FAILED\n" as *u8); sys_exit(2); return 2 }
811
812 var red: i64 = 0
813 if before > 0 { red = ((before - after) * 1000) / before }
814 dp("{\"organ\":\"nx_dedither\",\"w\":" as *u8); dnum(w)
815 dp(",\"h\":" as *u8); dnum(h)
816 dp(",\"radius\":" as *u8); dnum(r)
817 dp(",\"threshold\":" as *u8); dnum(thr)
818 dp(",\"mald_before_x1000\":" as *u8); dnum(before)
819 dp(",\"mald_after_x1000\":" as *u8); dnum(after)
820 dp(",\"noise_reduction_permil\":" as *u8); dnum(red)
821 var keep: i64 = 1000
822 if mg_before > 0 { keep = (mg_after * 1000) / mg_before }
823 dp(",\"meangrad_before_x1000\":" as *u8); dnum(mg_before)
824 dp(",\"meangrad_after_x1000\":" as *u8); dnum(mg_after)
825 dp(",\"structure_retained_permil\":" as *u8); dnum(keep)
826 dp(",\"scale\":" as *u8); dnum(scale)
827 dp(",\"out_w\":" as *u8); dnum(ow)
828 dp(",\"out_h\":" as *u8); dnum(oh)
829 dp(",\"original_untouched\":1}\n" as *u8)
830 return 0
831}