Skip to content

Commit 87fc1bc

Browse files
committed
feat: Use nearest-neighbor scaling in pi.Stretch
Because it is more accurate than the current algorithm and the performance is similar.
1 parent 610a13e commit 87fc1bc

File tree

12 files changed

+115
-15
lines changed

12 files changed

+115
-15
lines changed
223 Bytes
Loading
223 Bytes
Loading
223 Bytes
Loading
223 Bytes
Loading
226 Bytes
Loading
229 Bytes
Loading
234 Bytes
Loading
232 Bytes
Loading

internal/test/stretch/sprite.png

224 Bytes
Loading

sprite.go

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,31 +72,55 @@ func Stretch(sprite Sprite, dx, dy, dw, dh int) {
7272
targetStride := drawTarget.width - int(dst.W)
7373
srcSource := sprite.Source
7474

75-
if sprite.FlipY {
76-
src.Y += float64(dh-1) * stepY
77-
stepY *= -1
78-
}
75+
stepXAbs := src.W / dst.W
76+
stepYAbs := src.H / dst.H
7977

78+
// start sampling from half-step offsets
8079
if sprite.FlipX {
81-
src.X += float64(dw-1) * stepX
82-
stepX *= -1
80+
src.X += src.W - stepXAbs/2
81+
stepXAbs = -stepXAbs
82+
} else {
83+
src.X += stepXAbs / 2
84+
}
85+
86+
if sprite.FlipY {
87+
src.Y += src.H - stepYAbs/2
88+
stepYAbs = -stepYAbs
89+
} else {
90+
src.Y += stepYAbs / 2
8391
}
8492

85-
srcX, srcY := src.X, src.Y
93+
srcY := src.Y
8694

87-
for line := 0.0; line < dst.H; line++ {
88-
srcLineIdx := int(srcY) * srcSource.width // multiplication, but only once per line, so it's not a performance problem
95+
srcMaxX := int(src.X + src.W)
96+
srcMaxY := int(src.Y + src.H)
8997

90-
for cell := 0.0; cell < dst.W; cell++ {
91-
sourceColor := srcSource.data[srcLineIdx+int(srcX)] & ReadMask
98+
for line := 0.0; line < dst.H; line++ {
99+
syIndex := int(srcY)
100+
if syIndex < 0 {
101+
syIndex = 0
102+
} else if syIndex >= srcMaxY {
103+
syIndex = srcMaxY - 1
104+
}
105+
srcLineIdx := syIndex * srcSource.width
106+
107+
srcX := src.X
108+
for cell := 0; cell < int(dst.W); cell++ {
109+
sxIndex := int(srcX)
110+
if sxIndex < 0 {
111+
sxIndex = 0
112+
} else if sxIndex >= srcMaxX {
113+
sxIndex = srcMaxX - 1
114+
}
115+
116+
sourceColor := srcSource.data[srcLineIdx+sxIndex] & ReadMask
92117
targetColor := drawTarget.data[targetIdx] & TargetMask
93118
drawTarget.data[targetIdx] =
94119
ColorTables[(sourceColor|targetColor)>>6][sourceColor&(MaxColors-1)][targetColor&(MaxColors-1)]
95-
srcX += stepX
120+
srcX += stepXAbs
96121
targetIdx++
97122
}
98-
srcX = src.X
99-
srcY += stepY
123+
srcY += stepYAbs
100124
targetIdx += targetStride
101125
}
102126
}

0 commit comments

Comments
 (0)