nx_img_place.nx source
↩ module page · 76 lines · 3079 B
1// nx_img_place.nx -- place a decoded image onto a grayscale print page: luminance conversion + aspect-fit
2// + nearest-neighbor scale-blit. The back half of "print documents WITH images". Works on the raw pixels
3// from nx_png_decoder (any color type, 8/16-bit) and writes into the same 0=black..255=white page bitmap the
4// document renderer + URF encoder use. PURE (operates on caller buffers) -> never-brick. Sovereign.
5// genealogy_id: project-printer-management-ipp-sclass-2026-06-20 ; license_tier: ORIGINAL
6
7// Convert decoded image pixels -> grayscale (0=black..255=white), sw*sh bytes into out.
8// n_channels: 1=gray 2=gray+alpha 3=rgb 4=rgba. bit_depth 8 or 16 (16-bit: take the big-endian MSB).
9// Luminance = (R*77 + G*150 + B*29) >> 8 (Rec.601-ish integer weights summing to 256).
10func nx_img_to_gray(src: *u8, sw: i64, sh: i64, n_channels: i64, bit_depth: i64, out: *u8) -> i64 {
11 var sample_bytes: i64 = 1
12 if bit_depth == 16 { sample_bytes = 2 }
13 let stride: i64 = n_channels * sample_bytes
14 var y: i64 = 0
15 while y < sh {
16 var x: i64 = 0
17 while x < sw {
18 let base: i64 = (y * sw + x) * stride
19 var gray: i64 = 0
20 if n_channels <= 2 {
21 gray = src[base] as i64 // gray (alpha ignored)
22 } else {
23 let r: i64 = src[base] as i64
24 let g: i64 = src[base + sample_bytes] as i64
25 let b: i64 = src[base + 2 * sample_bytes] as i64
26 gray = (r * 77 + g * 150 + b * 29) >> 8
27 }
28 if gray > 255 { gray = 255 }
29 out[y * sw + x] = gray as u8
30 x = x + 1
31 }
32 y = y + 1
33 }
34 return 0
35}
36
37// Compute the largest WxH that fits within (maxW,maxH) preserving the source aspect ratio.
38func nx_img_fit(sw: i64, sh: i64, maxW: i64, maxH: i64, out_w: *i64, out_h: *i64) -> i64 {
39 if sw <= 0 { out_w[0] = maxW; out_h[0] = maxH; return 0 }
40 if sh <= 0 { out_w[0] = maxW; out_h[0] = maxH; return 0 }
41 var fw: i64 = maxW
42 var fh: i64 = maxW * sh / sw
43 if fh > maxH {
44 fh = maxH
45 fw = maxH * sw / sh
46 }
47 if fw < 1 { fw = 1 }
48 if fh < 1 { fh = 1 }
49 out_w[0] = fw
50 out_h[0] = fh
51 return 0
52}
53
54// Blit gray image (src, sw x sh) into page (W x H, 0=black..255=white) at top-left (dx,dy), scaled to
55// boxW x boxH via nearest-neighbor. Bounds-checked.
56func nx_img_blit(page: *u8, W: i64, H: i64, dx: i64, dy: i64,
57 src: *u8, sw: i64, sh: i64, boxW: i64, boxH: i64) -> i64 {
58 if boxW <= 0 { return 0 }
59 if boxH <= 0 { return 0 }
60 var ty: i64 = 0
61 while ty < boxH {
62 let sy: i64 = ty * sh / boxH
63 let py: i64 = dy + ty
64 if py >= 0 { if py < H {
65 var tx: i64 = 0
66 while tx < boxW {
67 let sx: i64 = tx * sw / boxW
68 let px: i64 = dx + tx
69 if px >= 0 { if px < W { page[py * W + px] = src[sy * sw + sx] } }
70 tx = tx + 1
71 }
72 } }
73 ty = ty + 1
74 }
75 return 0
76}