blur performance improved

This commit is contained in:
Ryan Oldenburg 2021-02-26 18:06:28 -06:00
parent 117cad90b2
commit 39d316d0d7
2 changed files with 54 additions and 27 deletions

View file

@ -354,22 +354,38 @@ proc blur*(image: Image, radius: float32) =
for y in 0 ..< image.height: for y in 0 ..< image.height:
for x in 0 ..< image.width: for x in 0 ..< image.width:
var values: array[4, uint32] var values: array[4, uint32]
for xb in -radius .. radius: if image.inside(x - radius, y) and image.inside(x + radius, y):
let for step in -radius .. radius:
sample = image[x + xb, y] let
a = lookup[xb + radius].uint32 sample = image.getRgbaUnsafe(x + step, y)
values += sample * a 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()) blurX.setRgbaUnsafe(x, y, values.rgba())
# Blur in the Y direction. # Blur in the Y direction.
for y in 0 ..< image.height: for y in 0 ..< image.height:
for x in 0 ..< image.width: for x in 0 ..< image.width:
var values: array[4, uint32] var values: array[4, uint32]
for yb in -radius .. radius: if image.inside(x, y - radius) and image.inside(x, y + radius):
let for step in -radius .. radius:
sample = blurX[x, y + yb] let
a = lookup[yb + radius].uint32 sample = blurX.getRgbaUnsafe(x, y + step)
values += sample * a 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()) image.setRgbaUnsafe(x, y, values.rgba())
proc newMask*(image: Image): Mask = proc newMask*(image: Image): Mask =

View file

@ -154,7 +154,7 @@ proc ceil*(mask: Mask) =
if mask.data[j] != 0: if mask.data[j] != 0:
mask.data[j] = 255 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. ## Applies Gaussian blur to the image given a radius.
let radius = round(radius).int let radius = round(radius).int
if radius == 0: if radius == 0:
@ -167,28 +167,39 @@ proc blur*(mask: Mask, radius: float32, offBounds: uint32 = 0) =
for y in 0 ..< mask.height: for y in 0 ..< mask.height:
for x in 0 ..< mask.width: for x in 0 ..< mask.width:
var value: uint32 var value: uint32
for xb in -radius .. radius: if mask.inside(x - radius, y) and mask.inside(x + radius, y):
var sample: uint32 for step in -radius .. radius:
if mask.inside(x + xb, y): let sample = mask.getValueUnsafe(x + step, y)
sample = mask.getValueUnsafe(x + xb, y) value += sample * lookup[step + radius].uint32
else: else:
sample = offBounds for step in -radius .. radius:
let a = lookup[xb + radius].uint32 var sample: uint32
value += sample * a 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) blurX.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
# Blur in the Y direction and modify image. # Blur in the Y direction and modify image.
for y in 0 ..< mask.height: for y in 0 ..< mask.height:
for x in 0 ..< mask.width: for x in 0 ..< mask.width:
var value: uint32 var value: uint32
for yb in -radius .. radius: if mask.inside(x, y - radius) and mask.inside(x, y + radius):
var sample: uint32 for step in -radius .. radius:
if blurX.inside(x, y + yb): let sample = blurX.getValueUnsafe(x, y + step)
sample = blurX.getValueUnsafe(x, y + yb) value += sample * lookup[step + radius].uint32
else: else:
sample = offBounds for step in -radius .. radius:
let a = lookup[yb + radius].uint32 var sample: uint32
value += sample * a 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) mask.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
when defined(release): when defined(release):