simpler + out of bounds color for image blur

This commit is contained in:
Ryan Oldenburg 2021-02-26 19:10:48 -06:00
parent 851c15f943
commit 004182a122
6 changed files with 64 additions and 50 deletions

View file

@ -317,7 +317,7 @@ proc invert*(target: Image | Mask) =
for j in i ..< target.data.len:
target.data[j] = (255 - target.data[j]).uint8
proc blur*(image: Image, radius: float32) =
proc blur*(image: Image, radius: float32, outOfBounds = ColorRGBX()) =
## Applies Gaussian blur to the image given a radius.
let radius = round(radius).int
if radius == 0:
@ -354,18 +354,23 @@ proc blur*(image: Image, radius: float32) =
for y in 0 ..< image.height:
for x in 0 ..< image.width:
var values: array[4, uint32]
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
for xx in x - radius ..< min(x + radius, 0):
let
sample = outOfBounds
a = lookup[xx - x + radius].uint32
values += sample * a
for xx in max(x - radius, 0) ..< min(x + radius, image.width):
let
sample = image.getRgbaUnsafe(xx, y)
a = lookup[xx - x + radius].uint32
values += sample * a
for xx in max(x - radius, image.width) ..< x + radius:
let
sample = outOfBounds
a = lookup[xx - x + radius].uint32
values += sample * a
blurX.setRgbaUnsafe(x, y, values.rgbx())
@ -373,18 +378,23 @@ proc blur*(image: Image, radius: float32) =
for y in 0 ..< image.height:
for x in 0 ..< image.width:
var values: array[4, uint32]
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
for yy in y - radius ..< min(y + radius, 0):
let
sample = outOfBounds
a = lookup[yy - y + radius].uint32
values += sample * a
for yy in max(y - radius, 0) ..< min(y + radius, image.height):
let
sample = blurX.getRgbaUnsafe(x, yy)
a = lookup[yy - y + radius].uint32
values += sample * a
for yy in max(y - radius, image.height) ..< y + radius:
let
sample = outOfBounds
a = lookup[yy - y + radius].uint32
values += sample * a
image.setRgbaUnsafe(x, y, values.rgbx())

View file

@ -167,18 +167,17 @@ proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) =
for y in 0 ..< mask.height:
for x in 0 ..< mask.width:
var value: uint32
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
for xx in x - radius ..< min(x + radius, 0):
let sample = outOfBounds
value += sample * lookup[xx - x + radius].uint32
for xx in max(x - radius, 0) ..< min(x + radius, mask.width):
let sample = mask.getValueUnsafe(xx, y)
value += sample * lookup[xx - x + radius].uint32
for xx in max(x - radius, mask.width) ..< x + radius:
let sample = outOfBounds
value += sample * lookup[xx - x + radius].uint32
blurX.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
@ -186,19 +185,17 @@ proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) =
for y in 0 ..< mask.height:
for x in 0 ..< mask.width:
var value: uint32
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
for yy in y - radius ..< min(y + radius, 0):
let sample = outOfBounds
value += sample * lookup[yy - y + radius].uint32
for yy in max(y - radius, 0) ..< min(y + radius, mask.height):
let sample = blurX.getValueUnsafe(x, yy)
value += sample * lookup[yy - y + radius].uint32
for yy in max(y - radius, mask.height) ..< y + radius:
let sample = outOfBounds
value += sample * lookup[yy - y + radius].uint32
mask.setValueUnsafe(x, y, (value div 1024 div 255).uint8)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -111,3 +111,10 @@ block:
image.fillRect(rect(25, 25, 50, 50), rgba(255, 255, 255, 255))
image.blur(20)
image.writeFile("tests/images/imageblur20.png")
block:
let image = newImage(100, 100)
image.fill(rgba(0, 0, 0, 255))
image.fillRect(rect(25, 25, 50, 50), rgba(255, 255, 255, 255))
image.blur(20, rgba(0, 0, 0, 255))
image.writeFile("tests/images/imageblur20oob.png")