Use matrix in all draw paths.
This commit is contained in:
parent
acc6822d0e
commit
cd612f9a6c
4 changed files with 31 additions and 60 deletions
|
@ -154,27 +154,31 @@ proc fraction(v: float32): float32 =
|
|||
result = abs(v)
|
||||
result = result - floor(result)
|
||||
|
||||
proc drawFast1*(a: Image, b: Image, x, y: int): Image =
|
||||
proc drawFast1*(a: Image, b: Image, mat: Mat3): Image =
|
||||
## Draws one image onto another using integer x,y offset with COPY.
|
||||
result = newImage(a.width, a.height)
|
||||
for yd in 0 ..< a.width:
|
||||
for xd in 0 ..< a.height:
|
||||
var rgba = a.getRgbaUnsafe(xd, yd)
|
||||
if b.inside(xd - x, yd - y):
|
||||
rgba = b.getRgbaUnsafe(xd - x, yd - y)
|
||||
result.setRgbaUnsafe(xd, yd, rgba)
|
||||
var matInv = mat.inverse()
|
||||
for y in 0 ..< a.width:
|
||||
for x in 0 ..< a.height:
|
||||
var rgba = a.getRgbaUnsafe(x, y)
|
||||
let srcPos = matInv * vec2(x.float32, y.float32)
|
||||
if b.inside(srcPos.x.floor.int, srcPos.y.floor.int):
|
||||
rgba = b.getRgbaUnsafe(srcPos.x.floor.int, srcPos.y.floor.int)
|
||||
result.setRgbaUnsafe(x, y, rgba)
|
||||
|
||||
proc drawFast2*(a: Image, b: Image, x, y: int, blendMode: BlendMode): Image =
|
||||
## Draws one image onto another using integer x,y offset with color blending.
|
||||
proc drawFast2*(a: Image, b: Image, mat: Mat3, blendMode: BlendMode): Image =
|
||||
## Draws one image onto another using matrix with color blending.
|
||||
result = newImage(a.width, a.height)
|
||||
for yd in 0 ..< a.width:
|
||||
for xd in 0 ..< a.height:
|
||||
var rgba = a.getRgbaUnsafe(xd, yd)
|
||||
if b.inside(xd - x, yd - y):
|
||||
var rgba2 = b.getRgbaUnsafe(xd - x, yd - y)
|
||||
var matInv = mat.inverse()
|
||||
for y in 0 ..< a.width:
|
||||
for x in 0 ..< a.height:
|
||||
var rgba = a.getRgbaUnsafe(x, y)
|
||||
let srcPos = matInv * vec2(x.float32, y.float32)
|
||||
if b.inside(srcPos.x.floor.int, srcPos.y.floor.int):
|
||||
let rgba2 = b.getRgbaUnsafe(srcPos.x.floor.int, srcPos.y.floor.int)
|
||||
if blendMode.hasEffect(rgba2):
|
||||
rgba = blendMode.mix(rgba, rgba2)
|
||||
result.setRgbaUnsafe(xd, yd, rgba)
|
||||
result.setRgbaUnsafe(x, y, rgba)
|
||||
|
||||
proc drawFast3*(a: Image, b: Image, mat: Mat3, blendMode: BlendMode): Image =
|
||||
## Draws one image onto another using matrix with color blending.
|
||||
|
@ -190,52 +194,21 @@ proc drawFast3*(a: Image, b: Image, mat: Mat3, blendMode: BlendMode): Image =
|
|||
rgba = blendMode.mix(rgba, rgba2)
|
||||
result.setRgbaUnsafe(x, y, rgba)
|
||||
|
||||
proc drawFast4*(a: Image, b: Image, mat: Mat3, blendMode: BlendMode): Image =
|
||||
## Draws one image onto another using matrix with color blending.
|
||||
result = newImage(a.width, a.height)
|
||||
var matInv = mat.inverse()
|
||||
for y in 0 ..< a.width:
|
||||
for x in 0 ..< a.height:
|
||||
var rgba = a.getRgbaUnsafe(x, y)
|
||||
let srcPos = matInv * vec2(x.float32, y.float32)
|
||||
if b.inside(srcPos.x.floor.int, srcPos.y.floor.int):
|
||||
let rgba2 = b.getRgbaUnsafe(srcPos.x.floor.int, srcPos.y.floor.int)
|
||||
if blendMode.hasEffect(rgba2):
|
||||
rgba = blendMode.mix(rgba, rgba2)
|
||||
result.setRgbaUnsafe(x, y, rgba)
|
||||
|
||||
proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image =
|
||||
## Draws one image onto another using matrix with color blending.
|
||||
|
||||
if mat[0, 0] == 1 and mat[0, 1] == 0 and
|
||||
mat[1, 0] == 0 and mat[1, 1] == 1 and
|
||||
mat[2, 0].fraction == 0.0 and mat[2, 1].fraction == 0.0:
|
||||
# Matrix is simple integer translation fast path:
|
||||
if blendMode == bmCopy:
|
||||
#echo "use 1"
|
||||
return drawFast1(
|
||||
a, b, mat[2, 0].int, mat[2, 1].int
|
||||
)
|
||||
else:
|
||||
#echo "use 2"
|
||||
return drawFast2(
|
||||
a, b, mat[2, 0].int, mat[2, 1].int, blendMode
|
||||
)
|
||||
|
||||
let ns = [-1.float32, 0, 1]
|
||||
if mat[0, 0] in ns and mat[0, 1] in ns and
|
||||
mat[1, 0] in ns and mat[1, 1] in ns and
|
||||
mat[2, 0].fraction == 0.0 and mat[2, 1].fraction == 0.0:
|
||||
echo "use 4"
|
||||
return drawFast4(
|
||||
a, b, mat, blendMode
|
||||
)
|
||||
|
||||
# Todo: if matrix is a simple flip -> fast path
|
||||
# 4 rotation x 3 flips = 12 combo
|
||||
#echo "use 3"
|
||||
if blendMode == bmCopy:
|
||||
return drawFast1(
|
||||
a, b, mat
|
||||
)
|
||||
else:
|
||||
return drawFast2(
|
||||
a, b, mat, blendMode
|
||||
)
|
||||
return drawFast3(a, b, mat, blendMode)
|
||||
|
||||
|
||||
proc draw*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal): Image =
|
||||
a.draw(b, translate(pos), blendMode)
|
||||
|
|
BIN
tests/images/drawFast1Rot.master.png
Normal file
BIN
tests/images/drawFast1Rot.master.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 B |
BIN
tests/images/drawFast1Rot.png
Normal file
BIN
tests/images/drawFast1Rot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 B |
|
@ -26,7 +26,7 @@ block:
|
|||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(100, 100)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
var c = a.drawFast1(b, x=25, y=25)
|
||||
var c = a.drawFast1(b, translate(vec2(25, 25)))
|
||||
c.writeAndCheck("tests/images/drawFast1.png")
|
||||
|
||||
block:
|
||||
|
@ -34,7 +34,7 @@ block:
|
|||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(100, 100)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
var c = a.drawFast2(b, x=25, y=25, bmCopy)
|
||||
var c = a.drawFast2(b, translate(vec2(25, 25)), bmCopy)
|
||||
c.writeAndCheck("tests/images/drawFast2.png")
|
||||
|
||||
block:
|
||||
|
@ -50,8 +50,6 @@ block:
|
|||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(100, 100)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
var c = a.drawFast4(b, translate(vec2(25.15, 25.15)) * rotationMat3(PI/2), bmCopy)
|
||||
c.writeAndCheck("tests/images/drawFast4Rot.png")
|
||||
|
||||
var d = a.drawFast3(b, translate(vec2(25.15, 25.15)) * rotationMat3(PI/2), bmCopy)
|
||||
d.writeAndCheck("tests/images/drawFast3Rot.png")
|
||||
var c = a.drawFast1(b, translate(vec2(25, 25)) * rotationMat3(PI/2))
|
||||
c.writeAndCheck("tests/images/drawFast1Rot.png")
|
||||
|
|
Loading…
Reference in a new issue