code wiki / (root) / nx_pwg_rle.nx

nx_pwg_rle.nx source

↩ module page · 217 lines · 9546 B

1// nx_pwg_rle.nx -- the PackBits-like run-length codec shared by PWG-Raster AND URF (Apple Raster). 2// This is the pixel-data encoding of "driverless" printing -- the bytes a real IPP printer rasterizes. 3// 4// Verified against the AUTHORITATIVE CUPS/PWG raster spec (sovereign-fetched, cited: 5// knowledge/fetched/cups_raster_spec.raw, lines 483-501): 6// - Each LINE begins with a 1-byte line-repeat count = (repeats - 1): 0x00 = appears once, 0xFF = 256x. 7// - Within a line, whole pixels ("colors") are PackBits-encoded: 8// control 0x00..0x7F -> REPEATED run: (ctrl+1) copies of the ONE following pixel (count 1..128) 9// control 0x80..0xFF -> LITERAL run: (257-ctrl) following pixels verbatim (count 2..128) 10// - one pixel = bpp bytes (sgray_8 -> 1 byte; sRGB -> 3 bytes). 11// Cross-checked on the spec's worked example line 12// 00 FE FFFF00 0000FF FFFF00 02 FFFFFF 00 00FF00 00 FFFFFF 13// = yellow,blue,yellow, white,white,white, green, white (proves the decoder matches the spec). 14// 15// NEVER-BRICK (#26): pure byte arithmetic; NO syscalls, no hardware access. Sovereign (no imports). 16// no_silent_failure: the decoder bounds-checks every read/write and returns -1 on truncation/overrun. 17// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL 18 19// pixels at logical index i and j of `line` (each bpp bytes) equal? 20func nx_rle_px_eq(line: *u8, i: i64, j: i64, bpp: i64) -> i64 { 21 var k: i64 = 0 22 var eq: i64 = 1 23 while k < bpp { 24 if (line[i * bpp + k] as i64) != (line[j * bpp + k] as i64) { eq = 0; k = bpp } 25 else { k = k + 1 } 26 } 27 return eq 28} 29 30// whole-scanline ya == yb equal? (width pixels, bpp bytes each) 31func nx_rle_line_eq(bitmap: *u8, width: i64, bpp: i64, ya: i64, yb: i64) -> i64 { 32 let pa: i64 = ya * width * bpp 33 let pb: i64 = yb * width * bpp 34 var k: i64 = 0 35 let nbytes: i64 = width * bpp 36 var eq: i64 = 1 37 while k < nbytes { 38 if (bitmap[pa + k] as i64) != (bitmap[pb + k] as i64) { eq = 0; k = nbytes } 39 else { k = k + 1 } 40 } 41 return eq 42} 43 44// Encode ONE scanline (no line-repeat byte). Returns advanced out offset. 45func nx_rle_encode_line(line: *u8, width: i64, bpp: i64, out: *u8, off0: i64) -> i64 { 46 var off: i64 = off0 47 var i: i64 = 0 48 while i < width { 49 // longest run of identical pixels at i (cap 128) 50 var run: i64 = 1 51 var cont: i64 = 1 52 while cont == 1 { 53 if (i + run) >= width { cont = 0 } 54 else { 55 if run >= 128 { cont = 0 } 56 else { 57 if nx_rle_px_eq(line, i, i + run, bpp) == 1 { run = run + 1 } 58 else { cont = 0 } 59 } 60 } 61 } 62 if run >= 2 { 63 out[off] = (run - 1) as u8 64 off = off + 1 65 var k: i64 = 0 66 while k < bpp { out[off] = line[i * bpp + k]; off = off + 1; k = k + 1 } 67 i = i + run 68 } else { 69 // literal: gather pixels until a run>=2 begins or 128 collected 70 let lit_start: i64 = i 71 var litcount: i64 = 0 72 var lc: i64 = 1 73 while lc == 1 { 74 if i >= width { lc = 0 } 75 else { 76 if litcount >= 128 { lc = 0 } 77 else { 78 var same: i64 = 0 79 if (i + 1) < width { if nx_rle_px_eq(line, i, i + 1, bpp) == 1 { same = 1 } } 80 if same == 1 { lc = 0 } 81 else { litcount = litcount + 1; i = i + 1 } 82 } 83 } 84 } 85 if litcount == 1 { 86 out[off] = 0 as u8 // a lone pixel -> repeat-of-1 (literal min is 2) 87 off = off + 1 88 var k2: i64 = 0 89 while k2 < bpp { out[off] = line[lit_start * bpp + k2]; off = off + 1; k2 = k2 + 1 } 90 } else { 91 out[off] = (257 - litcount) as u8 // literal control 0x81..0xFF 92 off = off + 1 93 var p: i64 = 0 94 while p < litcount { 95 var k3: i64 = 0 96 while k3 < bpp { out[off] = line[(lit_start + p) * bpp + k3]; off = off + 1; k3 = k3 + 1 } 97 p = p + 1 98 } 99 } 100 } 101 } 102 return off 103} 104 105// Encode a full page (height scanlines), collapsing consecutive identical lines via the line-repeat byte. 106// Returns total encoded byte length written at out[0..]. 107func nx_rle_encode_page(bitmap: *u8, width: i64, height: i64, bpp: i64, out: *u8) -> i64 { 108 var off: i64 = 0 109 var y: i64 = 0 110 while y < height { 111 var rep: i64 = 1 112 var c: i64 = 1 113 while c == 1 { 114 if (y + rep) >= height { c = 0 } 115 else { 116 if rep >= 256 { c = 0 } 117 else { 118 if nx_rle_line_eq(bitmap, width, bpp, y, y + rep) == 1 { rep = rep + 1 } 119 else { c = 0 } 120 } 121 } 122 } 123 out[off] = (rep - 1) as u8 124 off = off + 1 125 let lp: *u8 = ((bitmap as i64) + y * width * bpp) as *u8 126 off = nx_rle_encode_line(lp, width, bpp, out, off) 127 y = y + rep 128 } 129 return off 130} 131 132// Decode `height` lines of `width` pixels (bpp bytes each) from src[0..n) into out (capacity out_cap pixels). 133// Returns pixels decoded (= width*height) or -1 on any truncation/overrun (no_silent_failure). 134func nx_rle_decode(src: *u8, n: i64, width: i64, height: i64, bpp: i64, out: *u8, out_cap: i64) -> i64 { 135 var in_off: i64 = 0 136 var out_px: i64 = 0 137 var lines_done: i64 = 0 138 var err: i64 = 0 139 var keep: i64 = 1 140 while keep == 1 { 141 if lines_done >= height { keep = 0 } 142 else { 143 if in_off >= n { err = 1; keep = 0 } 144 else { 145 let LR: i64 = src[in_off] as i64 146 in_off = in_off + 1 147 let line_px0: i64 = out_px 148 var px: i64 = 0 149 var lk: i64 = 1 150 while lk == 1 { 151 if px >= width { lk = 0 } 152 else { 153 if in_off >= n { err = 1; lk = 0; keep = 0 } 154 else { 155 let ctrl: i64 = src[in_off] as i64 156 in_off = in_off + 1 157 if ctrl <= 127 { 158 let cnt: i64 = ctrl + 1 159 if (in_off + bpp) > n { err = 1; lk = 0; keep = 0 } 160 else { 161 var r: i64 = 0 162 while r < cnt { 163 if out_px >= out_cap { err = 1; r = cnt; lk = 0; keep = 0 } 164 else { 165 if px >= width { err = 1; r = cnt; lk = 0; keep = 0 } 166 else { 167 var k: i64 = 0 168 while k < bpp { out[out_px * bpp + k] = src[in_off + k]; k = k + 1 } 169 out_px = out_px + 1; px = px + 1; r = r + 1 170 } 171 } 172 } 173 in_off = in_off + bpp 174 } 175 } else { 176 let cnt2: i64 = 257 - ctrl 177 if (in_off + cnt2 * bpp) > n { err = 1; lk = 0; keep = 0 } 178 else { 179 var r2: i64 = 0 180 while r2 < cnt2 { 181 if out_px >= out_cap { err = 1; r2 = cnt2; lk = 0; keep = 0 } 182 else { 183 if px >= width { err = 1; r2 = cnt2; lk = 0; keep = 0 } 184 else { 185 var k2: i64 = 0 186 while k2 < bpp { out[out_px * bpp + k2] = src[in_off + k2]; k2 = k2 + 1 } 187 in_off = in_off + bpp; out_px = out_px + 1; px = px + 1; r2 = r2 + 1 188 } 189 } 190 } 191 } 192 } 193 } 194 } 195 } 196 if err == 0 { 197 if px != width { err = 1; keep = 0 } 198 else { 199 var rr: i64 = 0 200 while rr < LR { 201 if (out_px + width) > out_cap { err = 1; rr = LR; keep = 0 } 202 else { 203 var c2: i64 = 0 204 let nb: i64 = width * bpp 205 while c2 < nb { out[out_px * bpp + c2] = out[line_px0 * bpp + c2]; c2 = c2 + 1 } 206 out_px = out_px + width; rr = rr + 1 207 } 208 } 209 lines_done = lines_done + (LR + 1) 210 } 211 } 212 } 213 } 214 } 215 if err == 1 { return 0 - 1 } 216 return out_px 217}