code wiki / (root) / nx_bluenoise.nx

nx_bluenoise.nx

buildroot/runtime/nx_bluenoise.nx

22213 B475 linesdepth 3pulls 3 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_bluenoise.nx -- SOVEREIGN BLUE-NOISE MASK GENERATOR (Ulichney void-and-cluster, integer-exact). WHY THIS EXISTS: quantizing a photograph or a page of text to the ~16 grey levels an e-ink panel actually has is what produces the "ink on paper" look. Doing that quantization with a THRESHOLD MASK decides whether the result reads as paper texture or as a visible screen-door pattern. A blue-noise mask is the one whose thresholded pattern has an isotropic power spectrum with no low-frequency energy -- the eye's own low-pass then averages it to the right tone and never resolves structure. White noise clumps; ordered (Bayer) masks show a lattice. Blue noise is the state of the art and has been since Ulichney 1993. INTEGER-EXACT BY CONSTRUCTION: no float anywhere. The Gaussian is a 33-entry fixed-point table indexed by SQUARED distance, so the filter is exact and the same on every machine -- a mask that differed per host would make every downstream render non-reproducible. COST, STATED: the classical algorithm is O(N^2) in cell count. 64x64 is ~16.7M ops (fast); the published figure for 8192x8192 is about a MONTH, which is why the right shape is "generate a small mask ONCE, ship it as data, tile it" rather than generating at render time. The 128 cap below is that decision made explicit rather than discovered by a hang. IMPRECISION I CHOSE TO LIVE WITH (documented so the next reader does not trust it as exact): Ulichney's phases 3 and 4 reverse which class is the "minority" for filtering purposes. Because the filter is linear and toroidal, energy_of_zeros = constant - energy_of_ones, so "tightest cluster of 0s" and "largest void of 1s" select the SAME cell. The two phases therefore collapse into one loop here, exactly rather than approximately. nx_bluenoise gen <size> <out.raw> -- write size*size bytes, cell value = rank scaled to 0..255 nx_bluenoise stats <in.raw> <size> <fill> -- nearest-neighbour stats of the pattern thresholded at fill permil nx_bluenoise selftest -- the gate license_tier: ORIGINAL

dependencies 2 imports · 0 importers

nx_gate_verdict.nx nx_syscalls.nx nx_bluenoise.nx

imports: nx_gate_verdict.nxnx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main bn_puts sys_write sys_exit bn_seq bn_selftest gv_head gv_puts sys_write ↻ gv_ctr sys_mmap nxa_die sys_write ↻ sys_exit ↻ nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ sys_mmap ↻ bn_generate sys_mmap ↻ bn_splat bn_gauss sys_mmap ↻ bn_extreme gv_check gv_puts ↻ bn_nnstats sys_mmap ↻ bn_white bn_puts ↻ bn_num sys_write ↻

structs

none

consts

31const BN_MAGIC_4096: i64 = 4096
32const BN_MAGIC_3280: i64 = 3280
33const BN_MAGIC_2626: i64 = 2626
34const BN_MAGIC_2103: i64 = 2103
35const BN_MAGIC_1684: i64 = 1684
36const BN_MAGIC_1348: i64 = 1348
37const BN_MAGIC_1080: i64 = 1080
39const BN_MAX_SIZE: i64 = 128 // O(N^2): 128x128 is ~268M ops. Above this, generate offline and ship the bytes.
40const BN_MIN_SIZE: i64 = 8
41const BN_DEFAULT_SIZE: i64 = 64
42const BN_KERN_R: i64 = 4 // kernel radius; sigma=1.5 is negligible past 4 (weight 3/4096)
43const BN_KERN_MAXD2: i64 = 32 // max squared distance inside the radius-4 box
44const BN_FIX: i64 = 4096 // fixed-point scale for the Gaussian
45const BN_INIT_PERMIL: i64 = 100 // initial prototype fill (10%) -- Ulichney's recommended starting density
46const BN_LCG_A: i64 = 1103515245
47const BN_LCG_C: i64 = 12345
48const BN_LCG_M: i64 = 2147483648
49const BN_SEED: i64 = 20260808 // FIXED seed: the mask must be byte-identical on every host, forever
50const BN_BYTE_MAX: i64 = 256

functions

52func bn_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 2: bn_selftestmain calls 1: sys_write
53func bn_num(v: i64) -> i64
called by 2: bn_selftestmain calls 2: sys_writesys_mmap
66func bn_gauss(d2: i64) -> i64
called by 1: bn_splat calls 1: sys_mmap
80func bn_splat(energy: *i64, size: i64, cx: i64, cy: i64, sign: i64) -> i64
called by 1: bn_generate calls 1: bn_gauss
104func bn_extreme(bin: *i64, energy: *i64, n: i64, want: i64, hi: i64) -> i64
called by 1: bn_generate
123func bn_generate(size: i64, rank: *i64) -> i64
190func bn_nnstats(rank: *i64, size: i64, fill_permil: i64, out: *i64) -> i64
called by 2: bn_selftestmain calls 1: sys_mmap
256func bn_white(size: i64, rank: *i64) -> i64
called by 2: bn_selftestmain
271func bn_atoi(s: *u8) -> i64
called by 1: main
281func bn_write_raw(path: *u8, rank: *i64, n: i64) -> i64
292func bn_seq(a: *u8, b: *u8) -> i64
called by 1: main
302func bn_selftest() -> i64
383func main(argc: i64, argv: *i64) -> i64