code wiki / (root) / nx_img_resample.nx

nx_img_resample.nx source

↩ module page · 123 lines · 5246 B

1// nx_img_resample.nx -- selectable-model image resampler (the "easily 2// selectable models" ask). One entry point picks the model by id: 3// 4// nx_img_resample(model, src, sw, sh, nc, dst, dw, dh) 5// NEAREST -> nx_img_scale_nearest (this file) 6// BILINEAR -> nx_img_scale_bilinear (nx_img_scale.nx, reused) 7// BICUBIC -> nx_img_scale_bicubic (this file, Catmull-Rom 16-tap) 8// 9// All sovereign, hardware-rung-up (pure i64 fixed-point). New models (Lanczos, 10// and later a neural upscaler once the accel lock breaks) slot in as new ids. 11// Reuses _img_clamp / _img_srccoord / NX_IMG_Q from nx_img_scale (DRY #15). 12// license_tier: ORIGINAL 13 14import "nx_syscalls.nx" 15import "nx_img_scale.nx" 16const NX_MAGIC_32768: i64 = 32768 17const NX_MAGIC_65536: i64 = 65536 18const NX_MAGIC_131072: i64 = 131072 19const NX_MAGIC_8589934592: i64 = 8589934592 20const NX_MAGIC_17179869184: i64 = 17179869184 21 22const NX_RS_NEAREST: i64 = 0 23const NX_RS_BILINEAR: i64 = 1 24const NX_RS_BICUBIC: i64 = 2 25const NX_RS_N: i64 = 3 26 27// ===== nearest-neighbour ======================================= 28func nx_img_scale_nearest(src: *u8, sw: i64, sh: i64, nc: i64, 29 dst: *u8, dw: i64, dh: i64) -> i64 { 30 if sw <= 0 { return -1 } 31 if sh <= 0 { return -1 } 32 if dw <= 0 { return -1 } 33 if dh <= 0 { return -1 } 34 if nc <= 0 { return -1 } 35 var y: i64 = 0 36 while y < dh { 37 let sy: i64 = _img_srccoord(y, sh, dh) 38 let ny: i64 = _img_clamp((sy + NX_MAGIC_32768) / NX_MAGIC_65536, 0, sh - 1) 39 var x: i64 = 0 40 while x < dw { 41 let sx: i64 = _img_srccoord(x, sw, dw) 42 let nxx: i64 = _img_clamp((sx + NX_MAGIC_32768) / NX_MAGIC_65536, 0, sw - 1) 43 let sbase: i64 = (ny * sw + nxx) * nc 44 let dbase: i64 = (y * dw + x) * nc 45 var c: i64 = 0 46 while c < nc { 47 dst[dbase + c] = src[sbase + c] 48 c = c + 1 49 } 50 x = x + 1 51 } 52 y = y + 1 53 } 54 return 0 55} 56 57// ===== bicubic (Catmull-Rom, a=-0.5) =========================== 58// weights bracket b[i] = 2 * w_i * Q16 (signed Q16); sum(b) = 2*Q16 = 131072. 59func _bicubic_w(t: i64, b: *i64) -> i64 { 60 let t2: i64 = (t * t) / NX_MAGIC_65536 61 let t3: i64 = (t2 * t) / NX_MAGIC_65536 62 b[0] = 0 - t3 + 2 * t2 - t 63 b[1] = 3 * t3 - 5 * t2 + NX_MAGIC_131072 64 b[2] = 0 - (3 * t3) + 4 * t2 + t 65 b[3] = t3 - t2 66 return 0 67} 68 69func nx_img_scale_bicubic(src: *u8, sw: i64, sh: i64, nc: i64, 70 dst: *u8, dw: i64, dh: i64) -> i64 { 71 if sw <= 0 { return -1 } 72 if sh <= 0 { return -1 } 73 if dw <= 0 { return -1 } 74 if dh <= 0 { return -1 } 75 if nc <= 0 { return -1 } 76 let bx: *i64 = sys_mmap(64) as *i64 77 let by: *i64 = sys_mmap(64) as *i64 78 var y: i64 = 0 79 while y < dh { 80 let sy: i64 = _img_srccoord(y, sh, dh) 81 let yb: i64 = sy / NX_MAGIC_65536 82 _bicubic_w(sy - yb * NX_MAGIC_65536, by) 83 let r0: i64 = _img_clamp(yb - 1, 0, sh - 1) * sw 84 let r1: i64 = _img_clamp(yb, 0, sh - 1) * sw 85 let r2: i64 = _img_clamp(yb + 1, 0, sh - 1) * sw 86 let r3: i64 = _img_clamp(yb + 2, 0, sh - 1) * sw 87 var x: i64 = 0 88 while x < dw { 89 let sx: i64 = _img_srccoord(x, sw, dw) 90 let xb: i64 = sx / NX_MAGIC_65536 91 _bicubic_w(sx - xb * NX_MAGIC_65536, bx) 92 let x0: i64 = _img_clamp(xb - 1, 0, sw - 1) 93 let x1: i64 = _img_clamp(xb, 0, sw - 1) 94 let x2: i64 = _img_clamp(xb + 1, 0, sw - 1) 95 let x3: i64 = _img_clamp(xb + 2, 0, sw - 1) 96 let dbase: i64 = (y * dw + x) * nc 97 var c: i64 = 0 98 while c < nc { 99 let h0: i64 = bx[0]*(src[(r0+x0)*nc+c] as i64) + bx[1]*(src[(r0+x1)*nc+c] as i64) + bx[2]*(src[(r0+x2)*nc+c] as i64) + bx[3]*(src[(r0+x3)*nc+c] as i64) 100 let h1: i64 = bx[0]*(src[(r1+x0)*nc+c] as i64) + bx[1]*(src[(r1+x1)*nc+c] as i64) + bx[2]*(src[(r1+x2)*nc+c] as i64) + bx[3]*(src[(r1+x3)*nc+c] as i64) 101 let h2: i64 = bx[0]*(src[(r2+x0)*nc+c] as i64) + bx[1]*(src[(r2+x1)*nc+c] as i64) + bx[2]*(src[(r2+x2)*nc+c] as i64) + bx[3]*(src[(r2+x3)*nc+c] as i64) 102 let h3: i64 = bx[0]*(src[(r3+x0)*nc+c] as i64) + bx[1]*(src[(r3+x1)*nc+c] as i64) + bx[2]*(src[(r3+x2)*nc+c] as i64) + bx[3]*(src[(r3+x3)*nc+c] as i64) 103 let acc: i64 = by[0]*h0 + by[1]*h1 + by[2]*h2 + by[3]*h3 104 var v: i64 = (acc + NX_MAGIC_8589934592) / NX_MAGIC_17179869184 105 v = _img_clamp(v, 0, 255) 106 dst[dbase + c] = v as u8 107 c = c + 1 108 } 109 x = x + 1 110 } 111 y = y + 1 112 } 113 return 0 114} 115 116// ===== selectable dispatch ===================================== 117func nx_img_resample(model: i64, src: *u8, sw: i64, sh: i64, nc: i64, 118 dst: *u8, dw: i64, dh: i64) -> i64 { 119 if model == NX_RS_NEAREST { return nx_img_scale_nearest(src, sw, sh, nc, dst, dw, dh) } 120 if model == NX_RS_BILINEAR { return nx_img_scale_bilinear(src, sw, sh, nc, dst, dw, dh) } 121 if model == NX_RS_BICUBIC { return nx_img_scale_bicubic(src, sw, sh, nc, dst, dw, dh) } 122 return -1 123}