Skip to content

Commit 3c716a1

Browse files
authored
Fix scale factor calculation in fximgBlit function
1 parent bfafb07 commit 3c716a1

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

fximg.utils.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,124 @@ namespace helper {
6565
}
6666
}
6767

68+
export function fximgBlit(
69+
dst: Buffer,
70+
xDst: number, yDst: number,
71+
wDst: number, hDst: number,
72+
src: Buffer,
73+
xSrc: number, ySrc: number,
74+
wSrc: number, hSrc: number,
75+
transparent?: boolean,
76+
check?: boolean
77+
): boolean {
78+
if (fximgRoCheck(dst)) return false;
79+
80+
const dstW = fximgWidthOf(dst);
81+
const dstH = fximgHeightOf(dst);
82+
const srcW = fximgWidthOf(src);
83+
const srcH = fximgHeightOf(src);
84+
85+
// คำนวณ scale factor (จริง ๆ คือ ratio)
86+
const scaleX = wSrc / wSrc;
87+
const scaleY = hSrc / hSrc;
88+
89+
// Clip rectangle ทั้ง src และ dst (เหมือนมาตรฐาน)
90+
let clipWDst = wDst;
91+
let clipHDst = hDst;
92+
let clipWSrc = wSrc;
93+
let clipHSrc = hSrc;
94+
95+
if (xDst < 0) { clipWDst += xDst; clipWSrc += xDst; xSrc -= xDst; xDst = 0; }
96+
if (yDst < 0) { clipHDst += yDst; clipHSrc += yDst; ySrc -= yDst; yDst = 0; }
97+
if (xDst + clipWDst > dstW) clipWDst = dstW - xDst;
98+
if (yDst + clipHDst > dstH) clipHDst = dstH - yDst;
99+
100+
if (xSrc < 0) { clipWDst += xSrc; clipWSrc += xSrc; xSrc = 0; }
101+
if (ySrc < 0) { clipHDst += ySrc; clipHSrc += ySrc; ySrc = 0; }
102+
if (xSrc + clipWSrc > srcW) clipWSrc = srcW - xSrc;
103+
if (ySrc + clipHSrc > srcH) clipHSrc = srcH - ySrc;
104+
105+
if (clipWDst <= 0 || clipHDst <= 0 || clipWSrc <= 0 || clipHSrc <= 0) return false;
106+
107+
// ถ้า transparent=false และ check=false → อาจ optimize เร็วขึ้น แต่เวอร์ชันนี้ทำแบบ general ก่อน
108+
109+
const rowBuf = pins.createBuffer(clipHDst); // buffer ขนาดสูงสุดที่ copy จริง
110+
const dstRow = pins.createBuffer(dstH); // buffer เต็ม column ของ dst
111+
112+
let anyChange = false;
113+
114+
// วนทุกพิกเซลปลายทาง (nearest neighbor)
115+
for (let y = 0; y < dh; y++) {
116+
const srcY_float = sy + y * scaleY;
117+
const srcY = Math.floor(srcY_float + 0.5); // หรือ Math.round() ก็ได้
118+
119+
if (srcY < 0 || srcY >= srcH) continue;
120+
121+
for (let x = 0; x < dw; x++) {
122+
const srcX_float = sx + x * scaleX;
123+
const srcX = Math.floor(srcX_float + 0.5);
124+
125+
if (srcX < 0 || srcX >= srcW) continue;
126+
127+
const pixel = fximgGetPixel(src, srcX, srcY); // ต้องมี helper นี้ไหม? ถ้ายังไม่มีก็ implement ง่าย
128+
129+
if (transparent && pixel < 1) continue;
130+
131+
const old = fximgGetPixel(dst, dx + x, dy + y);
132+
if (old === pixel) continue;
133+
134+
fximgSetPixel(dst, dx + x, dy + y, pixel);
135+
anyChange = true;
136+
}
137+
}
138+
139+
return check ? anyChange : true;
140+
}
141+
142+
// 1. drawLine (Bresenham ปรับปรุงตามที่ภัทรแนะนำ - ใช้ sx/sy ตรวจทิศทาง ไม่เช็คจุดเริ่ม=จุดจบ)
143+
export function fximgDrawLine(fxpic: Buffer, x0: number, y0: number, x1: number, y1: number, color: number, idx?: number) {
144+
if (fximgRoCheck(fxpic)) return;
145+
color &= 0xF;
146+
if (x0 === x1 && y0 === y1) { fximgSetPixel(fxpic, x0, y0, color, idx); return; }
147+
idx = idx || 0;
148+
if (fximgIsOutOfRange(idx, fximgLengthOf(fxpic,))) return;
149+
const w = fximgWidthOf(fxpic);
150+
const h = fximgHeightOf(fxpic);
151+
const iw = idx * w;
152+
if ((x0 < 0 && x1 < 0) || (x0 >= w && x1 >= w) ||
153+
(y0 < 0 && y1 < 0) || (y0 >= h && y1 >= h)) return;
154+
155+
let dx = Math.abs(x1 - x0);
156+
let dy = Math.abs(y1 - y0);
157+
let sx = Math.clamp(-1, 1, x1 - x0);
158+
let sy = Math.clamp(-1, 1, y1 - y0);
159+
let err = dx - dy;
160+
161+
while (1) {
162+
if (((sx < 0 && x0 < 0) || (sx > 0 && x0 >= w) && sx !== 0) ||
163+
((sy < 0 && y0 < 0) || (sy > 0 && y0 >= h) && sy !== 0)) break;
164+
const buf = pins.createBuffer(hSrc);
165+
166+
// ดึง column จาก src (เริ่มจาก y=0 ของ buf)
167+
fximgGetRows(src, xSrc, buf, hSrc);
168+
169+
if (yDst === 0) {
170+
// Fast path: วางตรงหัว column
171+
fximgSetRows(dst, xDst, buf, hSrc);
172+
} else {
173+
// Slow path: merge กับข้อมูลเดิมที่ yDst
174+
const dstBuf = pins.createBuffer(dstFullH);
175+
fximgGetRows(dst, xDst, dstBuf, dstFullH);
176+
177+
// copy เข้าไปที่ offset yDst
178+
for (let i = 0; i < hSrc; i++) {
179+
dstBuf[yDst + i] = buf[i];
180+
}
181+
182+
fximgSetRows(dst, xDst, dstBuf, dstFullH);
183+
}
184+
}
185+
68186
export function fximgBlit(
69187
dst: Buffer,
70188
xDst: number, yDst: number,

0 commit comments

Comments
 (0)