code wiki / (root) / nx_color_meter.nx

nx_color_meter.nx source

↩ module page · 75 lines · 3462 B

1// nx_color_meter.nx -- Calculates CMYK toner coverage from an RGB bitmap and estimates remaining toner based on page yield. 2const NX_MAGIC_1000000: i64 = 1000000 3const NX_MAGIC_50000: i64 = 50000 4const NX_MAGIC_10000: i64 = 10000 5// nx_color_meter.nx -- per-color (CMYK) toner coverage measurement = the COLOR analog of the black-toner 6// real-coverage exceed. The operator's ask: "color toner monitoring, not just black." We own the bitmap, so 7// we measure REAL per-channel toner consumption with GCR under-color removal (black pulled into the K channel, 8// exactly as a color laser separates), giving honest C/M/Y/K consumption per page -- the per-color truth the 9// printer's lying per-color gauge can't be trusted for (HP "fake empty" = $5M settlement; per the sovereign 10// researcher's Ink/Toner-cartridge sources). PURE integer, NO float, NO syscalls -> never-brick #26. 11// Grounded: ISO/IEC 19798 (color toner page yield) + ISO/IEC 19752 (mono), 5%-coverage standard page. 12// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL 13 14const NX_CMY_C: i64 = 0 15const NX_CMY_M: i64 = 1 16const NX_CMY_Y: i64 = 2 17const NX_CMY_K: i64 = 3 18 19// Per-channel coverage in ppm (1e6 = 100% of that colorant over the page) from an RGB bitmap (3 bytes/pixel). 20// out4 receives [C, M, Y, K]. CMY demand = 255 - channel; GCR: K = min(C,M,Y) -> black toner, C/M/Y reduced 21// by K (so pure gray/black consumes K toner, not a muddy CMY mix -- how a real color laser prints). 22func nx_color_coverage(rgb: *u8, npix: i64, out4: *i64) -> i64 { 23 if npix <= 0 { out4[0] = 0; out4[1] = 0; out4[2] = 0; out4[3] = 0; return 0 } 24 var sc: i64 = 0 25 var sm: i64 = 0 26 var sy: i64 = 0 27 var sk: i64 = 0 28 var i: i64 = 0 29 while i < npix { 30 let base: i64 = i * 3 31 let r: i64 = rgb[base] as i64 32 let g: i64 = rgb[base + 1] as i64 33 let bb: i64 = rgb[base + 2] as i64 34 let c: i64 = 255 - r 35 let m: i64 = 255 - g 36 let y: i64 = 255 - bb 37 var k: i64 = c 38 if m < k { k = m } 39 if y < k { k = y } 40 sc = sc + (c - k) 41 sm = sm + (m - k) 42 sy = sy + (y - k) 43 sk = sk + k 44 i = i + 1 45 } 46 let denom: i64 = 255 * npix 47 out4[0] = (sc * NX_MAGIC_1000000) / denom 48 out4[1] = (sm * NX_MAGIC_1000000) / denom 49 out4[2] = (sy * NX_MAGIC_1000000) / denom 50 out4[3] = (sk * NX_MAGIC_1000000) / denom 51 return 0 52} 53 54// Per-color remaining toner in basis points (10000 = 100%) given that color's ISO-19798 page yield and the 55// cumulative coverage consumed (ppm summed over pages). capacity = yield_pages * 50000 ppm (the 5% ISO page). 56// -1 if yield unknown. Mirrors the mono nx_toner_ledger, per channel. 57func nx_color_remaining_bp(yield_pages: i64, consumed_ppm: i64) -> i64 { 58 if yield_pages <= 0 { return 0 - 1 } 59 let cap: i64 = yield_pages * NX_MAGIC_50000 60 if cap <= 0 { return 0 - 1 } 61 if consumed_ppm >= cap { return 0 } 62 return ((cap - consumed_ppm) * NX_MAGIC_10000) / cap 63} 64 65// sealed per-color status from a remaining-bp value: OK / LOW (<10%) / EMPTY (0) / UNKNOWN (-1). 66const NX_CSUP_OK: i64 = 1 67const NX_CSUP_LOW: i64 = 2 68const NX_CSUP_EMPTY: i64 = 3 69const NX_CSUP_UNKNOWN: i64 = 4 70func nx_color_status(remaining_bp: i64) -> i64 { 71 if remaining_bp < 0 { return NX_CSUP_UNKNOWN } 72 if remaining_bp == 0 { return NX_CSUP_EMPTY } 73 if remaining_bp < 1000 { return NX_CSUP_LOW } 74 return NX_CSUP_OK 75}