From 32c3072e0a92c04977aba2198447cc61b75bdc2f Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sun, 27 Jun 2021 15:55:13 -0500 Subject: [PATCH] get smooth a bit smarter (faster in solid color case) --- src/pixie/images.nim | 18 ++++++++++++--- src/pixie/masks.nim | 10 ++++++++- tests/benchmark_images_draw.nim | 39 ++++++++++++++++++++++++++++++--- 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/pixie/images.nim b/src/pixie/images.nim index b1bfe7e..7c5fd88 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -535,11 +535,18 @@ proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBX = x0y1 = image[x0, y1] x1y1 = image[x1, y1] - let + var topMix = x0y0 + if xFractional > 0 and x0y0 != x1y0: topMix = lerp(x0y0, x1y0, xFractional) + + var bottomMix = x0y1 + if xFractional > 0 and x0y1 != x1y1: bottomMix = lerp(x0y1, x1y1, xFractional) - lerp(topMix, bottomMix, yFractional) + if yFractional != 0 and topMix != bottomMix: + lerp(topMix, bottomMix, yFractional) + else: + topMix proc drawCorrect( a, b: Image | Mask, mat = mat3(), tiled = false, blendMode = bmNormal @@ -678,9 +685,11 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) = zeroMem(a.data[a.dataIndex(0, y)].addr, 4 * xMin) if smooth: + var srcPos = p + dx * xMin.float32 + dy * y.float32 + srcPos = vec2(max(0, srcPos.x), max(0, srcPos.y)) + for x in xMin ..< xMax: let - srcPos = p + dx * x.float32 + dy * y.float32 xFloat = srcPos.x - h yFloat = srcPos.y - h when type(a) is Image: @@ -701,6 +710,9 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) = else: # b is a Mask let sample = b.getValueSmooth(xFloat, yFloat) a.setValueUnsafe(x, y, masker(backdrop, sample)) + + srcPos += dx + else: var x = xMin when defined(amd64) and not defined(pixieNoSimd): diff --git a/src/pixie/masks.nim b/src/pixie/masks.nim index e81d16a..fdcaa01 100644 --- a/src/pixie/masks.nim +++ b/src/pixie/masks.nim @@ -173,10 +173,18 @@ proc getValueSmooth*(mask: Mask, x, y: float32): uint8 = x0y1 = mask[x0, y1] x1y1 = mask[x1, y1] + var topMix = x0y0 + if xFractional > 0 and x0y0 != x1y0: topMix = lerp(x0y0, x1y0, xFractional) + + var bottomMix = x0y1 + if xFractional > 0 and x0y1 != x1y1: bottomMix = lerp(x0y1, x1y1, xFractional) - lerp(topMix, bottomMix, yFractional) + if yFractional != 0 and topMix != bottomMix: + lerp(topMix, bottomMix, yFractional) + else: + topMix proc spread*(mask: Mask, spread: float32) = ## Grows the mask by spread. diff --git a/tests/benchmark_images_draw.nim b/tests/benchmark_images_draw.nim index bf4a925..3ae2443 100644 --- a/tests/benchmark_images_draw.nim +++ b/tests/benchmark_images_draw.nim @@ -40,7 +40,40 @@ block: a.fill(rgba(255, 0, 0, 255)) b.fill(rgba(0, 255, 0, 255)) - timeIt "draw big-on-bigger Smooth bmNormal": + timeIt "draw [scale 0.5]": + a.draw(b, translate(vec2(25, 25)) * scale(vec2(0.5, 0.5)), bmNormal) + keep(b) + +block: + let + a = newImage(1000, 1000) + b = newImage(500, 500) + a.fill(rgba(255, 0, 0, 255)) + b.fill(rgba(0, 255, 0, 255)) + + timeIt "draw Smooth [x translate]": + a.draw(b, translate(vec2(25.2, 0)), bmNormal) + keep(b) + +block: + let + a = newImage(1000, 1000) + b = newImage(500, 500) + a.fill(rgba(255, 0, 0, 255)) + b.fill(rgba(0, 255, 0, 255)) + + timeIt "draw Smooth [y translate]": + a.draw(b, translate(vec2(0, 25.2)), bmNormal) + keep(b) + +block: + let + a = newImage(1000, 1000) + b = newImage(500, 500) + a.fill(rgba(255, 0, 0, 255)) + b.fill(rgba(0, 255, 0, 255)) + + timeIt "draw Smooth [x + y translate]": a.draw(b, translate(vec2(25.2, 25.2)), bmNormal) keep(b) @@ -51,8 +84,8 @@ block: a.fill(rgba(255, 0, 0, 255)) b.fill(rgba(0, 255, 0, 255)) - timeIt "draw big-on-bigger bmNormal scale(0.5)": - a.draw(b, translate(vec2(25, 25)) * scale(vec2(0.5, 0.5)), bmNormal) + timeIt "draw Smooth [rotate 45 deg]": + a.draw(b, translate(vec2(0, 500)) * rotate(toRadians(45)), bmNormal) keep(b) block: