Fixed green.
|
@ -22,6 +22,12 @@ proc `$`*(image: Image): string =
|
||||||
## Display the image size and channels.
|
## Display the image size and channels.
|
||||||
"<Image " & $image.width & "x" & $image.height & ">"
|
"<Image " & $image.width & "x" & $image.height & ">"
|
||||||
|
|
||||||
|
proc fraction(v: float32): float32 =
|
||||||
|
## Returns unsigned fraction part of the float.
|
||||||
|
## -13.7868723 -> 0.7868723
|
||||||
|
result = abs(v)
|
||||||
|
result = result - floor(result)
|
||||||
|
|
||||||
proc inside*(image: Image, x, y: int): bool {.inline.} =
|
proc inside*(image: Image, x, y: int): bool {.inline.} =
|
||||||
## Returns true if (x, y) is inside the image.
|
## Returns true if (x, y) is inside the image.
|
||||||
x >= 0 and x < image.width and
|
x >= 0 and x < image.width and
|
||||||
|
@ -29,8 +35,9 @@ proc inside*(image: Image, x, y: int): bool {.inline.} =
|
||||||
|
|
||||||
proc inside1px*(image: Image, x, y: float): bool {.inline.} =
|
proc inside1px*(image: Image, x, y: float): bool {.inline.} =
|
||||||
## Returns true if (x, y) is inside the image.
|
## Returns true if (x, y) is inside the image.
|
||||||
x >= -1 and x < (image.width.float32 + 1) and
|
const px = 1
|
||||||
y >= -1 and y < (image.height.float32 + 1)
|
x >= -px and x < (image.width.float32 + px) and
|
||||||
|
y >= -px and y < (image.height.float32 + px)
|
||||||
|
|
||||||
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBA {.inline.} =
|
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBA {.inline.} =
|
||||||
## Gets a color from (x, y) coordinates.
|
## Gets a color from (x, y) coordinates.
|
||||||
|
@ -116,22 +123,39 @@ func lerp(a, b: Color, v: float): Color {.inline.} =
|
||||||
|
|
||||||
proc getRgbaSmooth*(image: Image, x, y: float64): ColorRGBA {.inline.} =
|
proc getRgbaSmooth*(image: Image, x, y: float64): ColorRGBA {.inline.} =
|
||||||
## Gets a pixel as (x, y) floats.
|
## Gets a pixel as (x, y) floats.
|
||||||
let
|
|
||||||
minX = floor(x).int
|
|
||||||
difX = (x - minX.float32)
|
|
||||||
minY = floor(y).int
|
|
||||||
difY = (y - minY.float32)
|
|
||||||
|
|
||||||
vX0Y0 = image[minX, minY].color()
|
proc toAlphy(c: Color): Color =
|
||||||
vX1Y0 = image[minX + 1, minY].color()
|
result.r = c.r * c.a
|
||||||
vX0Y1 = image[minX, minY + 1].color()
|
result.g = c.g * c.a
|
||||||
vX1Y1 = image[minX + 1, minY + 1].color()
|
result.b = c.b * c.a
|
||||||
|
result.a = c.a
|
||||||
|
|
||||||
|
proc fromAlphy(c: Color): Color =
|
||||||
|
if c.a == 0:
|
||||||
|
return
|
||||||
|
result.r = c.r / c.a
|
||||||
|
result.g = c.g / c.a
|
||||||
|
result.b = c.b / c.a
|
||||||
|
result.a = c.a
|
||||||
|
|
||||||
|
var
|
||||||
|
x = x # TODO: look at maybe +0.5
|
||||||
|
y = y # TODO: look at maybe +0.5
|
||||||
|
minX = x.floor.int
|
||||||
|
difX = x - x.floor
|
||||||
|
minY = y.floor.int
|
||||||
|
difY = y - y.floor
|
||||||
|
|
||||||
|
vX0Y0 = image[minX, minY].color().toAlphy()
|
||||||
|
vX1Y0 = image[minX + 1, minY].color().toAlphy()
|
||||||
|
vX0Y1 = image[minX, minY + 1].color().toAlphy()
|
||||||
|
vX1Y1 = image[minX + 1, minY + 1].color().toAlphy()
|
||||||
|
|
||||||
bottomMix = lerp(vX0Y0, vX1Y0, difX)
|
bottomMix = lerp(vX0Y0, vX1Y0, difX)
|
||||||
topMix = lerp(vX0Y1, vX1Y1, difX)
|
topMix = lerp(vX0Y1, vX1Y1, difX)
|
||||||
finalMix = lerp(bottomMix, topMix, difY)
|
finalMix = lerp(bottomMix, topMix, difY)
|
||||||
|
|
||||||
return finalMix.rgba()
|
return finalMix.fromAlphy().rgba()
|
||||||
|
|
||||||
proc hasEffect*(blendMode: BlendMode, rgba: ColorRGBA): bool =
|
proc hasEffect*(blendMode: BlendMode, rgba: ColorRGBA): bool =
|
||||||
## Returns true if applying rgba with current blend mode has effect.
|
## Returns true if applying rgba with current blend mode has effect.
|
||||||
|
@ -143,10 +167,6 @@ proc hasEffect*(blendMode: BlendMode, rgba: ColorRGBA): bool =
|
||||||
else:
|
else:
|
||||||
rgba.a > 0
|
rgba.a > 0
|
||||||
|
|
||||||
proc fraction(v: float32): float32 =
|
|
||||||
result = abs(v)
|
|
||||||
result = result - floor(result)
|
|
||||||
|
|
||||||
proc drawFast1*(a: Image, b: Image, mat: Mat3): Image =
|
proc drawFast1*(a: Image, b: Image, mat: Mat3): Image =
|
||||||
## Draws one image onto another using integer x,y offset with COPY.
|
## Draws one image onto another using integer x,y offset with COPY.
|
||||||
result = newImage(a.width, a.height)
|
result = newImage(a.width, a.height)
|
||||||
|
|
BIN
tests/images/centerRotation.master.png
Normal file
After Width: | Height: | Size: 900 B |
BIN
tests/images/centerRotation.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
tests/images/centerRotationWhite.master.png
Normal file
After Width: | Height: | Size: 932 B |
BIN
tests/images/centerRotationWhite.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 358 B After Width: | Height: | Size: 352 B |
BIN
tests/images/transCompose.c.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
tests/images/transCompose.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
|
@ -11,6 +11,47 @@ proc writeAndCheck(image: Image, fileName: string) =
|
||||||
assert image.height == master.height
|
assert image.height == master.height
|
||||||
assert image.data == master.data
|
assert image.data == master.data
|
||||||
|
|
||||||
|
block:
|
||||||
|
var a = newImage(100, 100)
|
||||||
|
a.fill(rgba(0, 0, 0, 0))
|
||||||
|
var b = newImage(50, 50)
|
||||||
|
b.fill(rgba(255, 92, 0, 255))
|
||||||
|
var c = a.drawFast3(
|
||||||
|
b,
|
||||||
|
translate(vec2(50, 50)) * rotationMat3(0.2789281382) * translate(vec2(-25, -25)),
|
||||||
|
bmNormal
|
||||||
|
)
|
||||||
|
c.writeAndCheck("tests/images/centerRotation.png")
|
||||||
|
|
||||||
|
block:
|
||||||
|
var a = newImage(100, 100)
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
var b = newImage(50, 50)
|
||||||
|
b.fill(rgba(255, 92, 0, 255))
|
||||||
|
var c = a.drawFast3(
|
||||||
|
b,
|
||||||
|
translate(vec2(50, 50)) * rotationMat3(0.2789281382) * translate(vec2(-25, -25)),
|
||||||
|
bmNormal
|
||||||
|
)
|
||||||
|
c.writeAndCheck("tests/images/centerRotationWhite.png")
|
||||||
|
|
||||||
|
|
||||||
|
block:
|
||||||
|
var a = newImage(100, 100)
|
||||||
|
a.fill(rgba(0, 0, 0, 0))
|
||||||
|
var b = newImage(50, 50)
|
||||||
|
b.fill(rgba(255, 92, 0, 255))
|
||||||
|
var c = a.drawFast3(
|
||||||
|
b,
|
||||||
|
translate(vec2(50, 50)) * rotationMat3(0.2789281382) * translate(vec2(-25, -25)),
|
||||||
|
bmNormal
|
||||||
|
)
|
||||||
|
c.writeAndCheck("tests/images/transCompose.c.png")
|
||||||
|
var d = newImage(100, 100)
|
||||||
|
d.fill(rgba(255, 255, 255, 255))
|
||||||
|
var e = d.draw(c)
|
||||||
|
e.writeAndCheck("tests/images/transCompose.png")
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var image = newImage(10, 10)
|
var image = newImage(10, 10)
|
||||||
image[0, 0] = rgba(255, 255, 255, 255)
|
image[0, 0] = rgba(255, 255, 255, 255)
|
||||||
|
|