move
This commit is contained in:
parent
d0294ebec7
commit
50a4687d67
1 changed files with 101 additions and 101 deletions
|
@ -369,6 +369,107 @@ proc invert*(target: Image | Mask) =
|
|||
for j in i ..< target.data.len:
|
||||
target.data[j] = (255 - target.data[j]).uint8
|
||||
|
||||
proc blur*(target: Image | Mask, radius: float32) =
|
||||
## Applies Gaussian blur to the image given a radius.
|
||||
let radius = round(radius).int
|
||||
if radius == 0:
|
||||
return
|
||||
|
||||
proc gaussianLookup(radius: int): seq[uint32] =
|
||||
## Compute lookup table for 1d Gaussian kernel.
|
||||
## Values are [0, 255] * 1024.
|
||||
result.setLen(radius * 2 + 1)
|
||||
|
||||
var
|
||||
floats = newSeq[float32](result.len)
|
||||
total = 0.0
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
s = radius.float32 / 2.2 # 2.2 matches Figma.
|
||||
x = xb.float32
|
||||
a = 1 / sqrt(2 * PI * s^2) * exp(-1 * x^2 / (2 * s^2))
|
||||
floats[xb + radius] = a
|
||||
total += a
|
||||
for xb in -radius .. radius:
|
||||
floats[xb + radius] = floats[xb + radius] / total
|
||||
|
||||
for i, f in floats:
|
||||
result[i] = round(f * 255 * 1024).uint32
|
||||
|
||||
let lookup = gaussianLookup(radius)
|
||||
|
||||
when type(target) is Image:
|
||||
|
||||
template `*`(sample: ColorRGBA, a: uint32): array[4, uint32] =
|
||||
[
|
||||
sample.r * a,
|
||||
sample.g * a,
|
||||
sample.b * a,
|
||||
sample.a * a
|
||||
]
|
||||
|
||||
template `+=`(values: var array[4, uint32], sample: array[4, uint32]) =
|
||||
values[0] += sample[0]
|
||||
values[1] += sample[1]
|
||||
values[2] += sample[2]
|
||||
values[3] += sample[3]
|
||||
|
||||
template rgba(values: array[4, uint32]): ColorRGBA =
|
||||
rgba(
|
||||
(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
|
||||
)
|
||||
|
||||
# Blur in the X direction.
|
||||
var blurX = newImage(target.width, target.height)
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var values: array[4, uint32]
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
sample = target[x + xb, y]
|
||||
a = lookup[xb + radius].uint32
|
||||
values += sample * a
|
||||
blurX.setRgbaUnsafe(x, y, values.rgba())
|
||||
|
||||
# Blur in the Y direction.
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.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
|
||||
target.setRgbaUnsafe(x, y, values.rgba())
|
||||
|
||||
else: # target is a Mask
|
||||
|
||||
# Blur in the X direction.
|
||||
var blurX = newMask(target.width, target.height)
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var value: uint32
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
sample = target[x + xb, y]
|
||||
a = lookup[xb + radius].uint32
|
||||
value += sample * a
|
||||
blurX.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
|
||||
|
||||
# Blur in the Y direction and modify image.
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var value: uint32
|
||||
for yb in -radius .. radius:
|
||||
let
|
||||
sample = blurX[x, y + yb]
|
||||
a = lookup[yb + radius].uint32
|
||||
value += sample * a
|
||||
target.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
|
||||
|
||||
proc newMask*(image: Image): Mask =
|
||||
## Returns a new mask using the alpha values of the parameter image.
|
||||
result = newMask(image.width, image.height)
|
||||
|
@ -508,107 +609,6 @@ proc draw*(
|
|||
) {.inline.} =
|
||||
mask.draw(image, translate(pos), blendMode)
|
||||
|
||||
proc blur*(target: Image | Mask, radius: float32) =
|
||||
## Applies Gaussian blur to the image given a radius.
|
||||
let radius = round(radius).int
|
||||
if radius == 0:
|
||||
return
|
||||
|
||||
proc gaussianLookup(radius: int): seq[uint32] =
|
||||
## Compute lookup table for 1d Gaussian kernel.
|
||||
## Values are [0, 255] * 1024.
|
||||
result.setLen(radius * 2 + 1)
|
||||
|
||||
var
|
||||
floats = newSeq[float32](result.len)
|
||||
total = 0.0
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
s = radius.float32 / 2.2 # 2.2 matches Figma.
|
||||
x = xb.float32
|
||||
a = 1 / sqrt(2 * PI * s^2) * exp(-1 * x^2 / (2 * s^2))
|
||||
floats[xb + radius] = a
|
||||
total += a
|
||||
for xb in -radius .. radius:
|
||||
floats[xb + radius] = floats[xb + radius] / total
|
||||
|
||||
for i, f in floats:
|
||||
result[i] = round(f * 255 * 1024).uint32
|
||||
|
||||
let lookup = gaussianLookup(radius)
|
||||
|
||||
when type(target) is Image:
|
||||
|
||||
template `*`(sample: ColorRGBA, a: uint32): array[4, uint32] =
|
||||
[
|
||||
sample.r * a,
|
||||
sample.g * a,
|
||||
sample.b * a,
|
||||
sample.a * a
|
||||
]
|
||||
|
||||
template `+=`(values: var array[4, uint32], sample: array[4, uint32]) =
|
||||
values[0] += sample[0]
|
||||
values[1] += sample[1]
|
||||
values[2] += sample[2]
|
||||
values[3] += sample[3]
|
||||
|
||||
template rgba(values: array[4, uint32]): ColorRGBA =
|
||||
rgba(
|
||||
(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
|
||||
)
|
||||
|
||||
# Blur in the X direction.
|
||||
var blurX = newImage(target.width, target.height)
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var values: array[4, uint32]
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
sample = target[x + xb, y]
|
||||
a = lookup[xb + radius].uint32
|
||||
values += sample * a
|
||||
blurX.setRgbaUnsafe(x, y, values.rgba())
|
||||
|
||||
# Blur in the Y direction.
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.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
|
||||
target.setRgbaUnsafe(x, y, values.rgba())
|
||||
|
||||
else: # target is a Mask
|
||||
|
||||
# Blur in the X direction.
|
||||
var blurX = newMask(target.width, target.height)
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var value: uint32
|
||||
for xb in -radius .. radius:
|
||||
let
|
||||
sample = target[x + xb, y]
|
||||
a = lookup[xb + radius].uint32
|
||||
value += sample * a
|
||||
blurX.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
|
||||
|
||||
# Blur in the Y direction and modify image.
|
||||
for y in 0 ..< target.height:
|
||||
for x in 0 ..< target.width:
|
||||
var value: uint32
|
||||
for yb in -radius .. radius:
|
||||
let
|
||||
sample = blurX[x, y + yb]
|
||||
a = lookup[yb + radius].uint32
|
||||
value += sample * a
|
||||
target.setValueUnsafe(x, y, (value div 1024 div 255).uint8)
|
||||
|
||||
proc drawUber(
|
||||
a, b: Image,
|
||||
p, dx, dy: Vec2,
|
||||
|
|
Loading…
Reference in a new issue