mask.unsafe[x, y]
This commit is contained in:
parent
ff1e6bd12d
commit
18a81b3d0e
3 changed files with 38 additions and 40 deletions
|
@ -689,7 +689,7 @@ proc drawCorrect(
|
||||||
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.unsafe[x, y] = blended
|
a.unsafe[x, y] = blended
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.unsafe[x, y]
|
||||||
when type(b) is Image:
|
when type(b) is Image:
|
||||||
let sample = b.getRgbaSmooth(xFloat, yFloat, tiled).a
|
let sample = b.getRgbaSmooth(xFloat, yFloat, tiled).a
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
|
@ -803,12 +803,12 @@ proc drawUber(
|
||||||
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.unsafe[x, y] = blended
|
a.unsafe[x, y] = blended
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.unsafe[x, y]
|
||||||
when type(b) is Image:
|
when type(b) is Image:
|
||||||
let sample = b.getRgbaSmooth(srcPos.x, srcPos.y).a
|
let sample = b.getRgbaSmooth(srcPos.x, srcPos.y).a
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let sample = b.getValueSmooth(srcPos.x, srcPos.y)
|
let sample = b.getValueSmooth(srcPos.x, srcPos.y)
|
||||||
a.setValueUnsafe(x, y, masker(backdrop, sample))
|
a.unsafe[x, y] = masker(backdrop, sample)
|
||||||
|
|
||||||
srcPos += dx
|
srcPos += dx
|
||||||
|
|
||||||
|
@ -900,16 +900,16 @@ proc drawUber(
|
||||||
blended = blender(backdrop, sample)
|
blended = blender(backdrop, sample)
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let
|
let
|
||||||
sample = b.getValueUnsafe(samplePos.x, samplePos.y)
|
sample = b.unsafe[samplePos.x, samplePos.y]
|
||||||
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
blended = blender(backdrop, rgbx(0, 0, 0, sample))
|
||||||
a.unsafe[x, y] = blended
|
a.unsafe[x, y] = blended
|
||||||
else: # a is a Mask
|
else: # a is a Mask
|
||||||
let backdrop = a.getValueUnsafe(x, y)
|
let backdrop = a.unsafe[x, y]
|
||||||
when type(b) is Image:
|
when type(b) is Image:
|
||||||
let sample = b.unsafe[samplePos.x, samplePos.y].a
|
let sample = b.unsafe[samplePos.x, samplePos.y].a
|
||||||
else: # b is a Mask
|
else: # b is a Mask
|
||||||
let sample = b.getValueUnsafe(samplePos.x, samplePos.y)
|
let sample = b.unsafe[samplePos.x, samplePos.y]
|
||||||
a.setValueUnsafe(x, y, masker(backdrop, sample))
|
a.unsafe[x, y] = masker(backdrop, sample)
|
||||||
|
|
||||||
srcPos += dx
|
srcPos += dx
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ type
|
||||||
width*, height*: int
|
width*, height*: int
|
||||||
data*: seq[uint8]
|
data*: seq[uint8]
|
||||||
|
|
||||||
|
UnsafeMask = object
|
||||||
|
mask: Mask
|
||||||
|
|
||||||
when defined(release):
|
when defined(release):
|
||||||
{.push checks: off.}
|
{.push checks: off.}
|
||||||
|
|
||||||
|
@ -38,29 +41,24 @@ proc inside*(mask: Mask, x, y: int): bool {.inline, raises: [].} =
|
||||||
proc dataIndex*(mask: Mask, x, y: int): int {.inline, raises: [].} =
|
proc dataIndex*(mask: Mask, x, y: int): int {.inline, raises: [].} =
|
||||||
mask.width * y + x
|
mask.width * y + x
|
||||||
|
|
||||||
proc getValueUnsafe*(mask: Mask, x, y: int): uint8 {.inline, raises: [].} =
|
template unsafe*(src: Mask): UnsafeMask =
|
||||||
## Gets a value from (x, y) coordinates.
|
UnsafeMask(mask: src)
|
||||||
## * No bounds checking *
|
|
||||||
## Make sure that x, y are in bounds.
|
|
||||||
## Failure in the assumptions will case unsafe memory reads.
|
|
||||||
result = mask.data[mask.dataIndex(x, y)]
|
|
||||||
|
|
||||||
proc setValueUnsafe*(mask: Mask, x, y: int, value: uint8) {.inline, raises: [].} =
|
template `[]`*(view: UnsafeMask, x, y: int): uint8 =
|
||||||
## Sets a value from (x, y) coordinates.
|
view.mask.data[view.mask.dataIndex(x, y)]
|
||||||
## * No bounds checking *
|
|
||||||
## Make sure that x, y are in bounds.
|
template `[]=`*(view: UnsafeMask, x, y: int, color: uint8) =
|
||||||
## Failure in the assumptions will case unsafe memory writes.
|
view.mask.data[view.mask.dataIndex(x, y)] = color
|
||||||
mask.data[mask.dataIndex(x, y)] = value
|
|
||||||
|
|
||||||
proc `[]`*(mask: Mask, x, y: int): uint8 {.inline, raises: [].} =
|
proc `[]`*(mask: Mask, x, y: int): uint8 {.inline, raises: [].} =
|
||||||
## Gets a value at (x, y) or returns transparent black if outside of bounds.
|
## Gets a value at (x, y) or returns transparent black if outside of bounds.
|
||||||
if mask.inside(x, y):
|
if mask.inside(x, y):
|
||||||
return mask.getValueUnsafe(x, y)
|
return mask.unsafe[x, y]
|
||||||
|
|
||||||
proc `[]=`*(mask: Mask, x, y: int, value: uint8) {.inline, raises: [].} =
|
proc `[]=`*(mask: Mask, x, y: int, value: uint8) {.inline, raises: [].} =
|
||||||
## Sets a value at (x, y) or does nothing if outside of bounds.
|
## Sets a value at (x, y) or does nothing if outside of bounds.
|
||||||
if mask.inside(x, y):
|
if mask.inside(x, y):
|
||||||
mask.setValueUnsafe(x, y, value)
|
mask.unsafe[x, y] = value
|
||||||
|
|
||||||
proc getValue*(mask: Mask, x, y: int): uint8 {.inline, raises: [].} =
|
proc getValue*(mask: Mask, x, y: int): uint8 {.inline, raises: [].} =
|
||||||
## Gets a value at (x, y) or returns transparent black if outside of bounds.
|
## Gets a value at (x, y) or returns transparent black if outside of bounds.
|
||||||
|
@ -144,11 +142,11 @@ proc minifyBy2*(mask: Mask, power = 1): Mask {.raises: [PixieError].} =
|
||||||
|
|
||||||
for x in x ..< result.width:
|
for x in x ..< result.width:
|
||||||
let value =
|
let value =
|
||||||
src.getValueUnsafe(x * 2 + 0, y * 2 + 0).uint32 +
|
src.unsafe[x * 2 + 0, y * 2 + 0].uint32 +
|
||||||
src.getValueUnsafe(x * 2 + 1, y * 2 + 0) +
|
src.unsafe[x * 2 + 1, y * 2 + 0] +
|
||||||
src.getValueUnsafe(x * 2 + 1, y * 2 + 1) +
|
src.unsafe[x * 2 + 1, y * 2 + 1] +
|
||||||
src.getValueUnsafe(x * 2 + 0, y * 2 + 1)
|
src.unsafe[x * 2 + 0, y * 2 + 1]
|
||||||
result.setValueUnsafe(x, y, (value div 4).uint8)
|
result.unsafe[x, y] = (value div 4).uint8
|
||||||
|
|
||||||
# Set src as this result for if we do another power
|
# Set src as this result for if we do another power
|
||||||
src = result
|
src = result
|
||||||
|
@ -163,7 +161,7 @@ proc magnifyBy2*(mask: Mask, power = 1): Mask {.raises: [PixieError].} =
|
||||||
for y in 0 ..< result.height:
|
for y in 0 ..< result.height:
|
||||||
for x in 0 ..< mask.width:
|
for x in 0 ..< mask.width:
|
||||||
let
|
let
|
||||||
value = mask.getValueUnsafe(x, y div scale)
|
value = mask.unsafe[x, y div scale]
|
||||||
scaledX = x * scale
|
scaledX = x * scale
|
||||||
idx = result.dataIndex(scaledX, y)
|
idx = result.dataIndex(scaledX, y)
|
||||||
for i in 0 ..< scale:
|
for i in 0 ..< scale:
|
||||||
|
@ -222,24 +220,24 @@ proc spread*(mask: Mask, spread: float32) {.raises: [PixieError].} =
|
||||||
for x in 0 ..< mask.width:
|
for x in 0 ..< mask.width:
|
||||||
var maxValue: uint8
|
var maxValue: uint8
|
||||||
for xx in max(x - spread, 0) .. min(x + spread, mask.width - 1):
|
for xx in max(x - spread, 0) .. min(x + spread, mask.width - 1):
|
||||||
let value = mask.getValueUnsafe(xx, y)
|
let value = mask.unsafe[xx, y]
|
||||||
if value > maxValue:
|
if value > maxValue:
|
||||||
maxValue = value
|
maxValue = value
|
||||||
if maxValue == 255:
|
if maxValue == 255:
|
||||||
break
|
break
|
||||||
spreadX.setValueUnsafe(y, x, maxValue)
|
spreadX.unsafe[y, x] = maxValue
|
||||||
|
|
||||||
# Spread in the Y direction and modify mask.
|
# Spread in the Y direction and modify mask.
|
||||||
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 maxValue: uint8
|
var maxValue: uint8
|
||||||
for yy in max(y - spread, 0) .. min(y + spread, mask.height - 1):
|
for yy in max(y - spread, 0) .. min(y + spread, mask.height - 1):
|
||||||
let value = spreadX.getValueUnsafe(yy, x)
|
let value = spreadX.unsafe[yy, x]
|
||||||
if value > maxValue:
|
if value > maxValue:
|
||||||
maxValue = value
|
maxValue = value
|
||||||
if maxValue == 255:
|
if maxValue == 255:
|
||||||
break
|
break
|
||||||
mask.setValueUnsafe(x, y, maxValue)
|
mask.unsafe[x, y] = maxValue
|
||||||
|
|
||||||
proc ceil*(mask: Mask) {.raises: [].} =
|
proc ceil*(mask: Mask) {.raises: [].} =
|
||||||
## A value of 0 stays 0. Anything else turns into 255.
|
## A value of 0 stays 0. Anything else turns into 255.
|
||||||
|
@ -277,10 +275,10 @@ proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) {.raises: [Pixie
|
||||||
for xx in x - radius ..< min(x + radius, 0):
|
for xx in x - radius ..< min(x + radius, 0):
|
||||||
value += outOfBounds * kernel[xx - x + radius].uint32
|
value += outOfBounds * kernel[xx - x + radius].uint32
|
||||||
for xx in max(x - radius, 0) .. min(x + radius, mask.width - 1):
|
for xx in max(x - radius, 0) .. min(x + radius, mask.width - 1):
|
||||||
value += mask.getValueUnsafe(xx, y) * kernel[xx - x + radius].uint32
|
value += mask.unsafe[xx, y] * kernel[xx - x + radius].uint32
|
||||||
for xx in max(x - radius, mask.width) .. x + radius:
|
for xx in max(x - radius, mask.width) .. x + radius:
|
||||||
value += outOfBounds * kernel[xx - x + radius].uint32
|
value += outOfBounds * kernel[xx - x + radius].uint32
|
||||||
blurX.setValueUnsafe(y, x, (value div 256 div 255).uint8)
|
blurX.unsafe[y, x] = (value div 256 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:
|
||||||
|
@ -289,10 +287,10 @@ proc blur*(mask: Mask, radius: float32, outOfBounds: uint8 = 0) {.raises: [Pixie
|
||||||
for yy in y - radius ..< min(y + radius, 0):
|
for yy in y - radius ..< min(y + radius, 0):
|
||||||
value += outOfBounds * kernel[yy - y + radius].uint32
|
value += outOfBounds * kernel[yy - y + radius].uint32
|
||||||
for yy in max(y - radius, 0) .. min(y + radius, mask.height - 1):
|
for yy in max(y - radius, 0) .. min(y + radius, mask.height - 1):
|
||||||
value += blurX.getValueUnsafe(yy, x) * kernel[yy - y + radius].uint32
|
value += blurX.unsafe[yy, x] * kernel[yy - y + radius].uint32
|
||||||
for yy in max(y - radius, mask.height) .. y + radius:
|
for yy in max(y - radius, mask.height) .. y + radius:
|
||||||
value += outOfBounds * kernel[yy - y + radius].uint32
|
value += outOfBounds * kernel[yy - y + radius].uint32
|
||||||
mask.setValueUnsafe(x, y, (value div 256 div 255).uint8)
|
mask.unsafe[x, y] = (value div 256 div 255).uint8
|
||||||
|
|
||||||
when defined(release):
|
when defined(release):
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
@ -1449,10 +1449,10 @@ proc fillCoverage(
|
||||||
while x < startX + coverages.len:
|
while x < startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage != 0 or blendMode == bmExcludeMask:
|
if coverage != 0 or blendMode == bmExcludeMask:
|
||||||
let backdrop = mask.getValueUnsafe(x, y)
|
let backdrop = mask.unsafe[x, y]
|
||||||
mask.setValueUnsafe(x, y, masker(backdrop, coverage))
|
mask.unsafe[x, y] = masker(backdrop, coverage)
|
||||||
elif blendMode == bmMask:
|
elif blendMode == bmMask:
|
||||||
mask.setValueUnsafe(x, y, 0)
|
mask.unsafe[x, y] = 0
|
||||||
inc x
|
inc x
|
||||||
|
|
||||||
if blendMode == bmMask:
|
if blendMode == bmMask:
|
||||||
|
@ -1564,8 +1564,8 @@ proc fillHits(
|
||||||
x += 16
|
x += 16
|
||||||
|
|
||||||
for x in x ..< fillStart + fillLen:
|
for x in x ..< fillStart + fillLen:
|
||||||
let backdrop = mask.getValueUnsafe(x, y)
|
let backdrop = mask.unsafe[x, y]
|
||||||
mask.setValueUnsafe(x, y, masker(backdrop, 255))
|
mask.unsafe[x, y] = masker(backdrop, 255)
|
||||||
|
|
||||||
if blendMode == bmMask:
|
if blendMode == bmMask:
|
||||||
mask.clearUnsafe(0, y, startX, y)
|
mask.clearUnsafe(0, y, startX, y)
|
||||||
|
|
Loading…
Reference in a new issue