From 39d316d0d70484bec9a562774a1c36b1498c958a Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Fri, 26 Feb 2021 18:06:28 -0600 Subject: [PATCH] blur performance improved --- src/pixie/images.nim | 36 +++++++++++++++++++++++++---------- src/pixie/masks.nim | 45 +++++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/pixie/images.nim b/src/pixie/images.nim index 31c0a51..6767622 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -354,22 +354,38 @@ proc blur*(image: Image, radius: float32) = for y in 0 ..< image.height: for x in 0 ..< image.width: var values: array[4, uint32] - for xb in -radius .. radius: - let - sample = image[x + xb, y] - a = lookup[xb + radius].uint32 - values += sample * a + if image.inside(x - radius, y) and image.inside(x + radius, y): + for step in -radius .. radius: + let + sample = image.getRgbaUnsafe(x + step, y) + a = lookup[step + radius].uint32 + values += sample * a + else: + for step in -radius .. radius: + let + sample = image[x + step, y] + a = lookup[step + radius].uint32 + values += sample * a + blurX.setRgbaUnsafe(x, y, values.rgba()) # Blur in the Y direction. for y in 0 ..< image.height: for x in 0 ..< image.width: var values: array[4, uint32] - for yb in -radius .. radius: - let - sample = blurX[x, y + yb] - a = lookup[yb + radius].uint32 - values += sample * a + if image.inside(x, y - radius) and image.inside(x, y + radius): + for step in -radius .. radius: + let + sample = blurX.getRgbaUnsafe(x, y + step) + a = lookup[step + radius].uint32 + values += sample * a + else: + for step in -radius .. radius: + let + sample = blurX[x, y + step] + a = lookup[step + radius].uint32 + values += sample * a + image.setRgbaUnsafe(x, y, values.rgba()) proc newMask*(image: Image): Mask = diff --git a/src/pixie/masks.nim b/src/pixie/masks.nim index 3dc529b..57f14ee 100644 --- a/src/pixie/masks.nim +++ b/src/pixie/masks.nim @@ -154,7 +154,7 @@ proc ceil*(mask: Mask) = if mask.data[j] != 0: mask.data[j] = 255 -proc blur*(mask: Mask, radius: float32, offBounds: uint32 = 0) = +proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) = ## Applies Gaussian blur to the image given a radius. let radius = round(radius).int if radius == 0: @@ -167,28 +167,39 @@ proc blur*(mask: Mask, radius: float32, offBounds: uint32 = 0) = for y in 0 ..< mask.height: for x in 0 ..< mask.width: var value: uint32 - for xb in -radius .. radius: - var sample: uint32 - if mask.inside(x + xb, y): - sample = mask.getValueUnsafe(x + xb, y) - else: - sample = offBounds - let a = lookup[xb + radius].uint32 - value += sample * a + if mask.inside(x - radius, y) and mask.inside(x + radius, y): + for step in -radius .. radius: + let sample = mask.getValueUnsafe(x + step, y) + value += sample * lookup[step + radius].uint32 + else: + for step in -radius .. radius: + var sample: uint32 + if mask.inside(x + step, y): + sample = mask.getValueUnsafe(x + step, y) + else: + sample = outOfBounds + value += sample * lookup[step + radius].uint32 + blurX.setValueUnsafe(x, y, (value div 1024 div 255).uint8) # Blur in the Y direction and modify image. for y in 0 ..< mask.height: for x in 0 ..< mask.width: var value: uint32 - for yb in -radius .. radius: - var sample: uint32 - if blurX.inside(x, y + yb): - sample = blurX.getValueUnsafe(x, y + yb) - else: - sample = offBounds - let a = lookup[yb + radius].uint32 - value += sample * a + if mask.inside(x, y - radius) and mask.inside(x, y + radius): + for step in -radius .. radius: + let sample = blurX.getValueUnsafe(x, y + step) + value += sample * lookup[step + radius].uint32 + else: + for step in -radius .. radius: + var sample: uint32 + if blurX.inside(x, y + step): + sample = blurX.getValueUnsafe(x, y + step) + else: + sample = outOfBounds + let a = lookup[step + radius].uint32 + value += sample * a + mask.setValueUnsafe(x, y, (value div 1024 div 255).uint8) when defined(release):