|
@ -544,12 +544,12 @@ proc getRgbaSmooth*(
|
||||||
## Gets a interpolated color with float point coordinates.
|
## Gets a interpolated color with float point coordinates.
|
||||||
## Pixes outside the image are transparent.
|
## Pixes outside the image are transparent.
|
||||||
let
|
let
|
||||||
x0 = x.int
|
x0 = x.floor.int
|
||||||
y0 = y.int
|
y0 = y.floor.int
|
||||||
x1 = x0 + 1
|
x1 = x0 + 1
|
||||||
y1 = y0 + 1
|
y1 = y0 + 1
|
||||||
xFractional = x.fractional
|
xFractional = x - x.floor
|
||||||
yFractional = y.fractional
|
yFractional = y - y.floor
|
||||||
|
|
||||||
var x0y0, x1y0, x0y1, x1y1: ColorRGBX
|
var x0y0, x1y0, x0y1, x1y1: ColorRGBX
|
||||||
if wrapped:
|
if wrapped:
|
||||||
|
@ -588,21 +588,28 @@ proc drawCorrect(
|
||||||
|
|
||||||
var
|
var
|
||||||
matInv = mat.inverse()
|
matInv = mat.inverse()
|
||||||
|
# Compute movement vectors
|
||||||
|
p = matInv * vec2(0 + h, 0 + h)
|
||||||
|
dx = matInv * vec2(1 + h, 0 + h) - p
|
||||||
|
dy = matInv * vec2(0 + h, 1 + h) - p
|
||||||
|
filterBy2 = max(dx.length, dy.length)
|
||||||
b = b
|
b = b
|
||||||
|
|
||||||
block: # Shrink by 2 as needed
|
while filterBy2 >= 2.0:
|
||||||
var
|
b = b.minifyBy2()
|
||||||
p = matInv * vec2(0 + h, 0 + h)
|
p /= 2
|
||||||
dx = matInv * vec2(1 + h, 0 + h) - p
|
dx /= 2
|
||||||
dy = matInv * vec2(0 + h, 1 + h) - p
|
dy /= 2
|
||||||
minFilterBy2 = max(dx.length, dy.length)
|
filterBy2 /= 2
|
||||||
|
matInv = scale(vec2(1/2, 1/2)) * matInv
|
||||||
|
|
||||||
while minFilterBy2 >= 2:
|
while filterBy2 <= 0.5:
|
||||||
b = b.minifyBy2()
|
b = b.magnifyBy2()
|
||||||
dx /= 2
|
p *= 2
|
||||||
dy /= 2
|
dx *= 2
|
||||||
minFilterBy2 /= 2
|
dy *= 2
|
||||||
matInv = matInv * scale(vec2(0.5, 0.5))
|
filterBy2 *= 2
|
||||||
|
matInv = scale(vec2(2, 2)) * matInv
|
||||||
|
|
||||||
for y in 0 ..< a.height:
|
for y in 0 ..< a.height:
|
||||||
for x in 0 ..< a.width:
|
for x in 0 ..< a.width:
|
||||||
|
@ -653,16 +660,22 @@ proc drawUber(
|
||||||
p = matInv * vec2(0 + h, 0 + h)
|
p = matInv * vec2(0 + h, 0 + h)
|
||||||
dx = matInv * vec2(1 + h, 0 + h) - p
|
dx = matInv * vec2(1 + h, 0 + h) - p
|
||||||
dy = matInv * vec2(0 + h, 1 + h) - p
|
dy = matInv * vec2(0 + h, 1 + h) - p
|
||||||
minFilterBy2 = max(dx.length, dy.length)
|
filterBy2 = max(dx.length, dy.length)
|
||||||
b = b
|
b = b
|
||||||
|
|
||||||
while minFilterBy2 >= 2.0:
|
while filterBy2 >= 2.0:
|
||||||
b = b.minifyBy2()
|
b = b.minifyBy2()
|
||||||
p /= 2
|
p /= 2
|
||||||
dx /= 2
|
dx /= 2
|
||||||
dy /= 2
|
dy /= 2
|
||||||
minFilterBy2 /= 2
|
filterBy2 /= 2
|
||||||
matInv = matInv * scale(vec2(0.5, 0.5))
|
|
||||||
|
while filterBy2 <= 0.5:
|
||||||
|
b = b.magnifyBy2()
|
||||||
|
p *= 2
|
||||||
|
dx *= 2
|
||||||
|
dy *= 2
|
||||||
|
filterBy2 *= 2
|
||||||
|
|
||||||
let smooth = not(
|
let smooth = not(
|
||||||
dx.length == 1.0 and
|
dx.length == 1.0 and
|
||||||
|
@ -716,29 +729,26 @@ proc drawUber(
|
||||||
|
|
||||||
if smooth:
|
if smooth:
|
||||||
var srcPos = p + dx * xMin.float32 + dy * y.float32
|
var srcPos = p + dx * xMin.float32 + dy * y.float32
|
||||||
srcPos = vec2(max(0, srcPos.x), max(0, srcPos.y))
|
srcPos = vec2(srcPos.x - h, srcPos.y - h)
|
||||||
|
|
||||||
for x in xMin ..< xMax:
|
for x in xMin ..< xMax:
|
||||||
let
|
|
||||||
xFloat = srcPos.x - h
|
|
||||||
yFloat = srcPos.y - h
|
|
||||||
when type(a) is Image:
|
when type(a) is Image:
|
||||||
let backdrop = a.getRgbaUnsafe(x, y)
|
let backdrop = a.getRgbaUnsafe(x, y)
|
||||||
when type(b) is Image:
|
when type(b) is Image:
|
||||||
let
|
let
|
||||||
sample = b.getRgbaSmooth(xFloat, yFloat)
|
sample = b.getRgbaSmooth(srcPos.x, srcPos.y)
|
||||||
blended = blender(backdrop, sample)
|
blended = blender(backdrop, sample)
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let
|
let
|
||||||
sample = b.getValueSmooth(xFloat, yFloat)
|
sample = b.getValueSmooth(srcPos.x, srcPos.y)
|
||||||
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.setRgbaUnsafe(x, y, blended)
|
a.setRgbaUnsafe(x, y, blended)
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.getValueUnsafe(x, y)
|
||||||
when type(b) is Image:
|
when type(b) is Image:
|
||||||
let sample = b.getRgbaSmooth(xFloat, yFloat).a
|
let sample = b.getRgbaSmooth(srcPos.x, srcPos.y).a
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let sample = b.getValueSmooth(xFloat, yFloat)
|
let sample = b.getValueSmooth(srcPos.x, srcPos.y)
|
||||||
a.setValueUnsafe(x, y, masker(backdrop, sample))
|
a.setValueUnsafe(x, y, masker(backdrop, sample))
|
||||||
|
|
||||||
srcPos += dx
|
srcPos += dx
|
||||||
|
|
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 338 B |
BIN
tests/images/diffs/smooth10.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
tests/images/diffs/smooth11.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/images/diffs/smooth12.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 841 B After Width: | Height: | Size: 574 B |
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 368 B |
Before Width: | Height: | Size: 415 B After Width: | Height: | Size: 418 B |
BIN
tests/images/diffs/smooth5.png
Normal file
After Width: | Height: | Size: 585 B |
BIN
tests/images/diffs/smooth6.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
tests/images/diffs/smooth7.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
tests/images/diffs/smooth8.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
tests/images/diffs/smooth9.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
tests/images/masters/smooth10.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
tests/images/masters/smooth11.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/images/masters/smooth12.png
Normal file
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 763 B After Width: | Height: | Size: 699 B |
BIN
tests/images/masters/smooth5.png
Normal file
After Width: | Height: | Size: 581 B |
BIN
tests/images/masters/smooth6.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
tests/images/masters/smooth7.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
tests/images/masters/smooth8.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
tests/images/masters/smooth9.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 376 B |
BIN
tests/images/rendered/smooth10.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/images/rendered/smooth11.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
tests/images/rendered/smooth12.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 814 B |
Before Width: | Height: | Size: 366 B After Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 437 B |
BIN
tests/images/rendered/smooth5.png
Normal file
After Width: | Height: | Size: 680 B |
BIN
tests/images/rendered/smooth6.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
tests/images/rendered/smooth7.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
tests/images/rendered/smooth8.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/images/rendered/smooth9.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/images/turtle.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
tests/images/turtle@10x.png
Normal file
After Width: | Height: | Size: 165 KiB |
|
@ -138,22 +138,20 @@ proc doDiff(rendered: Image, name: string) =
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let
|
let
|
||||||
image = newImage(100, 100)
|
a = newImage(100, 100)
|
||||||
path = newPath()
|
b = newImage(99, 99)
|
||||||
path.rect(0, 0, 99, 99)
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
image.fillPath(path, rgba(0, 0, 0, 255), translate(vec2(0.5, 0.5)))
|
b.fill(rgbx(0, 0, 0, 255))
|
||||||
doDiff(image, "smooth1")
|
a.draw(b, translate(vec2(0.5, 0.5)))
|
||||||
|
doDiff(a, "smooth1")
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let
|
let
|
||||||
a = newImage(100, 100)
|
a = newImage(100, 100)
|
||||||
b = newImage(100, 100)
|
b = newImage(50, 50)
|
||||||
path = newPath()
|
|
||||||
path.rect(-25, -25, 50, 50)
|
|
||||||
path.transform(rotate(45 * PI.float32 / 180))
|
|
||||||
b.fillPath(path, rgba(0, 0, 0, 255), translate(vec2(50, 50)))
|
|
||||||
a.fill(rgba(255, 255, 255, 255))
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
a.draw(b, translate(vec2(0, 0.4)))
|
b.fill(rgbx(0, 0, 0, 255))
|
||||||
|
a.draw(b, translate(vec2(0, 50)) * rotate(45.toRadians))
|
||||||
doDiff(a, "smooth2")
|
doDiff(a, "smooth2")
|
||||||
|
|
||||||
block:
|
block:
|
||||||
|
@ -173,3 +171,81 @@ block:
|
||||||
b.fill(rgba(0, 0, 0, 255))
|
b.fill(rgba(0, 0, 0, 255))
|
||||||
a.draw(b, translate(vec2(25.2, 25.6)))
|
a.draw(b, translate(vec2(25.2, 25.6)))
|
||||||
doDiff(a, "smooth4")
|
doDiff(a, "smooth4")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = newImage(10, 10)
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
b.fill(rgbx(255, 0, 0, 255))
|
||||||
|
let m = translate(vec2(50, 50)) * rotate(30.toRadians)
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth5")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(50, 50)) * rotate(30.toRadians)
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth6")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle@10x.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(50, 50)) * rotate(30.toRadians) * scale(vec2(0.1, 0.1))
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth7")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = scale(vec2(2, 2))
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth8")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(1, 1)) * scale(vec2(2, 2))
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth9")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(0.5, 0.5)) * scale(vec2(2, 2))
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth10")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(-43.29, -103.87)) *
|
||||||
|
rotate(-15.toRadians) *
|
||||||
|
scale(vec2(263.86/40, 263.86/40))
|
||||||
|
a.draw(b, m)
|
||||||
|
doDiff(a, "smooth11")
|
||||||
|
|
||||||
|
block:
|
||||||
|
let
|
||||||
|
a = newImage(100, 100)
|
||||||
|
b = readImage(&"tests/images/turtle.png")
|
||||||
|
a.fill(rgba(255, 255, 255, 255))
|
||||||
|
let m = translate(vec2(50, 50)) * rotate(-5.toRadians)
|
||||||
|
a.draw(b, m * translate(vec2(0,0)))
|
||||||
|
a.draw(b, m * translate(vec2(-40,0)))
|
||||||
|
a.draw(b, m * translate(vec2(-40,-40)))
|
||||||
|
a.draw(b, m * translate(vec2(0,-40)))
|
||||||
|
doDiff(a, "smooth12")
|
||||||
|
|