Merge pull request #298 from guzba/master

blur 2x faster for images
This commit is contained in:
treeform 2021-10-03 19:32:06 -07:00 committed by GitHub
commit 6e400197df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 15 additions and 34 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -475,10 +475,10 @@ proc blur*(
template rgbx(values: array[4, uint32]): ColorRGBX =
rgbx(
(values[0] div 1024 div 255).uint8,
(values[1] div 1024 div 255).uint8,
(values[2] div 1024 div 255).uint8,
(values[3] div 1024 div 255).uint8
(values[0] div 256 div 255).uint8,
(values[1] div 256 div 255).uint8,
(values[2] div 256 div 255).uint8,
(values[3] div 256 div 255).uint8
)
# Blur in the X direction. Store with dimensions swapped for reading later.
@ -488,13 +488,10 @@ proc blur*(
var values: array[4, uint32]
for xx in x - radius ..< min(x + radius, 0):
values += outOfBounds * kernel[xx - x + radius]
for xx in max(x - radius, 0) .. min(x + radius, image.width - 1):
values += image.getRgbaUnsafe(xx, y) * kernel[xx - x + radius]
for xx in max(x - radius, image.width) .. x + radius:
values += outOfBounds * kernel[xx - x + radius]
blurX.setRgbaUnsafe(y, x, rgbx(values))
# Blur in the Y direction.
@ -503,13 +500,10 @@ proc blur*(
var values: array[4, uint32]
for yy in y - radius ..< min(y + radius, 0):
values += outOfBounds * kernel[yy - y + radius]
for yy in max(y - radius, 0) .. min(y + radius, image.height - 1):
values += blurX.getRgbaUnsafe(yy, x) * kernel[yy - y + radius]
for yy in max(y - radius, image.height) .. y + radius:
values += outOfBounds * kernel[yy - y + radius]
image.setRgbaUnsafe(x, y, rgbx(values))
proc newMask*(image: Image): Mask {.raises: [PixieError].} =

View file

@ -3,9 +3,9 @@ import chroma, vmath
when defined(amd64) and not defined(pixieNoSimd):
import nimsimd/sse2
proc gaussianKernel*(radius: int): seq[uint32] {.raises: [].} =
proc gaussianKernel*(radius: int): seq[uint16] {.raises: [].} =
## Compute lookup table for 1d Gaussian kernel.
## Values are [0, 255] * 1024.
## Values are [0, 255] * 256.
result.setLen(radius * 2 + 1)
var
@ -19,9 +19,8 @@ proc gaussianKernel*(radius: int): seq[uint32] {.raises: [].} =
total += a
for step in -radius .. radius:
floats[step + radius] = floats[step + radius] / total
for i, f in floats:
result[i] = round(f * 255 * 1024).uint32
result[i] = round(f * 255 * 256).uint16
proc applyOpacity*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
if opacity == 0:

View file

@ -275,30 +275,24 @@ proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) {.raises: [Pixie
for x in 0 ..< mask.width:
var value: uint32
for xx in x - radius ..< min(x + radius, 0):
value += outOfBounds * kernel[xx - x + radius]
value += outOfBounds * kernel[xx - x + radius].uint32
for xx in max(x - radius, 0) .. min(x + radius, mask.width - 1):
value += mask.getValueUnsafe(xx, y) * kernel[xx - x + radius]
value += mask.getValueUnsafe(xx, y) * kernel[xx - x + radius].uint32
for xx in max(x - radius, mask.width) .. x + radius:
value += outOfBounds * kernel[xx - x + radius]
blurX.setValueUnsafe(y, x, (value div 1024 div 255).uint8)
value += outOfBounds * kernel[xx - x + radius].uint32
blurX.setValueUnsafe(y, x, (value div 256 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 yy in y - radius ..< min(y + radius, 0):
value += outOfBounds * kernel[yy - y + radius]
value += outOfBounds * kernel[yy - y + radius].uint32
for yy in max(y - radius, 0) .. min(y + radius, mask.height - 1):
value += blurX.getValueUnsafe(yy, x) * kernel[yy - y + radius]
value += blurX.getValueUnsafe(yy, x) * kernel[yy - y + radius].uint32
for yy in max(y - radius, mask.height) .. y + radius:
value += outOfBounds * kernel[yy - y + radius]
mask.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
value += outOfBounds * kernel[yy - y + radius].uint32
mask.setValueUnsafe(x, y, (value div 256 div 255).uint8)
when defined(release):
{.pop.}

View file

@ -41,13 +41,10 @@ proc blurSlower*(
var values: array[4, uint32]
for xx in x - radius ..< min(x + radius, 0):
values += outOfBounds * kernel[xx - x + radius]
for xx in max(x - radius, 0) .. min(x + radius, image.width - 1):
values += image.getRgbaUnsafe(xx, y) * kernel[xx - x + radius]
for xx in max(x - radius, image.width) .. x + radius:
values += outOfBounds * kernel[xx - x + radius]
blurX.setRgbaUnsafe(x, y, rgbx(values))
# Blur in the Y direction.
@ -56,13 +53,10 @@ proc blurSlower*(
var values: array[4, uint32]
for yy in y - radius ..< min(y + radius, 0):
values += outOfBounds * kernel[yy - y + radius]
for yy in max(y - radius, 0) .. min(y + radius, image.height - 1):
values += blurX.getRgbaUnsafe(x, yy) * kernel[yy - y + radius]
for yy in max(y - radius, image.height) .. y + radius:
values += outOfBounds * kernel[yy - y + radius]
image.setRgbaUnsafe(x, y, rgbx(values))
let image = newImage(1920, 1080)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB