Merge pull request #82 from guzba/master
much faster blends, couple other little things
This commit is contained in:
commit
d1664de1d7
4 changed files with 473 additions and 381 deletions
|
@ -1,5 +1,5 @@
|
||||||
## Blending modes.
|
## Blending modes.
|
||||||
import chroma, math
|
import chroma, math, common
|
||||||
|
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
import nimsimd/sse2
|
import nimsimd/sse2
|
||||||
|
@ -34,7 +34,165 @@ type
|
||||||
bmIntersectMask
|
bmIntersectMask
|
||||||
bmExcludeMask
|
bmExcludeMask
|
||||||
|
|
||||||
Mixer* = proc(a, b: ColorRGBA): ColorRGBA
|
Blender* = proc(a, b: ColorRGBA): ColorRGBA
|
||||||
|
|
||||||
|
when defined(release):
|
||||||
|
{.push checks: off.}
|
||||||
|
|
||||||
|
proc min(a, b: uint32): uint32 {.inline.} =
|
||||||
|
if a < b: a else: b
|
||||||
|
|
||||||
|
proc max(a, b: uint32): uint32 {.inline.} =
|
||||||
|
if a > b: a else: b
|
||||||
|
|
||||||
|
proc screenPremultiplied(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
(255 - ((255 - backdrop) * (255 - source)) div 255).uint8
|
||||||
|
|
||||||
|
proc hardLightPremultiplied(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
if source <= 127:
|
||||||
|
((backdrop * 2 * source) div 255).uint8
|
||||||
|
else:
|
||||||
|
screenPremultiplied(backdrop, 2 * source - 255)
|
||||||
|
|
||||||
|
proc blendAlpha(backdrop, source: uint8): uint8 {.inline.} =
|
||||||
|
source + ((backdrop.uint32 * (255 - source)) div 255).uint8
|
||||||
|
|
||||||
|
proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline.} =
|
||||||
|
if backdrop.a == 0:
|
||||||
|
return source
|
||||||
|
if source.a == 255:
|
||||||
|
return source
|
||||||
|
if source.a == 0:
|
||||||
|
return backdrop
|
||||||
|
|
||||||
|
let k = (255 - source.a.uint32)
|
||||||
|
result.r = source.r + ((backdrop.r.uint32 * k) div 255).uint8
|
||||||
|
result.g = source.g + ((backdrop.g.uint32 * k) div 255).uint8
|
||||||
|
result.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendDarkenPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = min(backdrop.r, source.r)
|
||||||
|
result.g = min(backdrop.g, source.g)
|
||||||
|
result.b = min(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendMultiplyPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = ((backdrop.r.uint32 * source.r) div 255).uint8
|
||||||
|
result.g = ((backdrop.g.uint32 * source.g) div 255).uint8
|
||||||
|
result.b = ((backdrop.b.uint32 * source.b) div 255).uint8
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendLinearBurnPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = min(0, backdrop.r.uint32 + source.r.uint32 - 255).uint8
|
||||||
|
result.g = min(0, backdrop.g.uint32 + source.g.uint32 - 255).uint8
|
||||||
|
result.b = min(0, backdrop.b.uint32 + source.b.uint32 - 255).uint8
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendLightenPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = max(backdrop.r, source.r)
|
||||||
|
result.g = max(backdrop.g, source.g)
|
||||||
|
result.b = max(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendColorBurnPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
if backdrop == 255:
|
||||||
|
255.uint8
|
||||||
|
elif source == 0:
|
||||||
|
0
|
||||||
|
else:
|
||||||
|
255 - min(255, (255 * (255 - backdrop)) div source).uint8
|
||||||
|
result.r = blend(backdrop.r, source.r)
|
||||||
|
result.g = blend(backdrop.g, source.g)
|
||||||
|
result.b = blend(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendScreenPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = screenPremultiplied(backdrop.r, source.r)
|
||||||
|
result.g = screenPremultiplied(backdrop.g, source.g)
|
||||||
|
result.b = screenPremultiplied(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendLinearDodgePremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = min(backdrop.r.uint32 + source.r, 255).uint8
|
||||||
|
result.g = min(backdrop.g.uint32 + source.g, 255).uint8
|
||||||
|
result.b = min(backdrop.b.uint32 + source.b, 255).uint8
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendColorDodgePremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
if backdrop == 0:
|
||||||
|
0.uint8
|
||||||
|
elif source == 255:
|
||||||
|
255
|
||||||
|
else:
|
||||||
|
min(255, (255 * backdrop) div (255 - source)).uint8
|
||||||
|
result.r = blend(backdrop.r, source.r)
|
||||||
|
result.g = blend(backdrop.g, source.g)
|
||||||
|
result.b = blend(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendOverlayPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = hardLightPremultiplied(source.r, backdrop.r)
|
||||||
|
result.g = hardLightPremultiplied(source.g, backdrop.g)
|
||||||
|
result.b = hardLightPremultiplied(source.b, backdrop.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendHardLightyPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = hardLightPremultiplied(backdrop.r, source.r)
|
||||||
|
result.g = hardLightPremultiplied(backdrop.g, source.g)
|
||||||
|
result.b = hardLightPremultiplied(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendDifferencePremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
result.r = max(backdrop.r, source.r) - min(backdrop.r, source.r)
|
||||||
|
result.g = max(backdrop.g, source.g) - min(backdrop.g, source.g)
|
||||||
|
result.b = max(backdrop.b, source.b) - min(backdrop.b, source.b)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
proc blendExclusionPremultiplied(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
max(0, backdrop + source - (2 * backdrop * source) div 255).uint8
|
||||||
|
result.r = blend(backdrop.r.uint32, source.r.uint32)
|
||||||
|
result.g = blend(backdrop.g.uint32, source.g.uint32)
|
||||||
|
result.b = blend(backdrop.b.uint32, source.b.uint32)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
|
proc blendNormalPremultiplied*(backdrop, source: M128i): M128i {.inline.} =
|
||||||
|
let
|
||||||
|
alphaMask = mm_set1_epi32(cast[int32](0xff000000))
|
||||||
|
oddMask = mm_set1_epi16(cast[int16](0xff00))
|
||||||
|
div255 = mm_set1_epi16(cast[int16](0x8081))
|
||||||
|
|
||||||
|
# Shortcuts didn't help (backdrop.a == 0, source.a == 0, source.a == 255)
|
||||||
|
|
||||||
|
var
|
||||||
|
sourceAlpha = mm_and_si128(source, alphaMask)
|
||||||
|
backdropEven = mm_slli_epi16(backdrop, 8)
|
||||||
|
backdropOdd = mm_and_si128(backdrop, oddMask)
|
||||||
|
|
||||||
|
sourceAlpha = mm_or_si128(sourceAlpha, mm_srli_epi32(sourceAlpha, 16))
|
||||||
|
|
||||||
|
let k = mm_sub_epi32(
|
||||||
|
mm_set1_epi32(cast[int32]([0.uint8, 255, 0, 255])),
|
||||||
|
sourceAlpha
|
||||||
|
)
|
||||||
|
|
||||||
|
backdropEven = mm_mulhi_epu16(backdropEven, k)
|
||||||
|
backdropOdd = mm_mulhi_epu16(backdropOdd, k)
|
||||||
|
|
||||||
|
backdropEven = mm_srli_epi16(mm_mulhi_epu16(backdropEven, div255), 7)
|
||||||
|
backdropOdd = mm_srli_epi16(mm_mulhi_epu16(backdropOdd, div255), 7)
|
||||||
|
|
||||||
|
mm_add_epi8(
|
||||||
|
source,
|
||||||
|
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
|
||||||
|
)
|
||||||
|
|
||||||
|
when defined(release):
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
proc `+`*(a, b: Color): Color {.inline.} =
|
proc `+`*(a, b: Color): Color {.inline.} =
|
||||||
result.r = a.r + b.r
|
result.r = a.r + b.r
|
||||||
|
@ -72,18 +230,18 @@ proc `-`*(c: Color, v: float32): Color {.inline.} =
|
||||||
result.b = c.b - v
|
result.b = c.b - v
|
||||||
result.a = c.a - v
|
result.a = c.a - v
|
||||||
|
|
||||||
proc screen(backdrop, source: float32): float32 {.inline.} =
|
# proc screen(backdrop, source: float32): float32 {.inline.} =
|
||||||
1 - (1 - backdrop) * (1 - source)
|
# 1 - (1 - backdrop) * (1 - source)
|
||||||
|
|
||||||
proc hardLight(backdrop, source: float32): float32 {.inline.} =
|
# proc hardLight(backdrop, source: float32): float32 {.inline.} =
|
||||||
if source <= 0.5:
|
# if source <= 0.5:
|
||||||
backdrop * 2 * source
|
# backdrop * 2 * source
|
||||||
else:
|
# else:
|
||||||
screen(backdrop, 2 * source - 1)
|
# screen(backdrop, 2 * source - 1)
|
||||||
|
|
||||||
proc softLight(backdrop, source: float32): float32 {.inline.} =
|
# proc softLight(backdrop, source: float32): float32 {.inline.} =
|
||||||
## Pegtop
|
# ## Pegtop
|
||||||
(1 - 2 * source) * backdrop ^ 2 + 2 * source * backdrop
|
# (1 - 2 * source) * backdrop ^ 2 + 2 * source * backdrop
|
||||||
|
|
||||||
proc Lum(C: Color): float32 {.inline.} =
|
proc Lum(C: Color): float32 {.inline.} =
|
||||||
0.3 * C.r + 0.59 * C.g + 0.11 * C.b
|
0.3 * C.r + 0.59 * C.g + 0.11 * C.b
|
||||||
|
@ -131,103 +289,103 @@ proc alphaFix(backdrop, source, mixed: Color): Color =
|
||||||
result.g /= result.a
|
result.g /= result.a
|
||||||
result.b /= result.a
|
result.b /= result.a
|
||||||
|
|
||||||
proc blendNormalFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendNormalFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = source
|
# result = source
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendDarkenFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendDarkenFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = min(backdrop.r, source.r)
|
# result.r = min(backdrop.r, source.r)
|
||||||
result.g = min(backdrop.g, source.g)
|
# result.g = min(backdrop.g, source.g)
|
||||||
result.b = min(backdrop.b, source.b)
|
# result.b = min(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendMultiplyFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendMultiplyFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = backdrop.r * source.r
|
# result.r = backdrop.r * source.r
|
||||||
result.g = backdrop.g * source.g
|
# result.g = backdrop.g * source.g
|
||||||
result.b = backdrop.b * source.b
|
# result.b = backdrop.b * source.b
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendLinearBurnFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendLinearBurnFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = backdrop.r + source.r - 1
|
# result.r = backdrop.r + source.r - 1
|
||||||
result.g = backdrop.g + source.g - 1
|
# result.g = backdrop.g + source.g - 1
|
||||||
result.b = backdrop.b + source.b - 1
|
# result.b = backdrop.b + source.b - 1
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendColorBurnFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendColorBurnFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
proc blend(backdrop, source: float32): float32 {.inline.} =
|
# proc blend(backdrop, source: float32): float32 {.inline.} =
|
||||||
if backdrop == 1:
|
# if backdrop == 1:
|
||||||
1.0
|
# 1.0
|
||||||
elif source == 0:
|
# elif source == 0:
|
||||||
0.0
|
# 0.0
|
||||||
else:
|
# else:
|
||||||
1.0 - min(1, (1 - backdrop) / source)
|
# 1.0 - min(1, (1 - backdrop) / source)
|
||||||
result.r = blend(backdrop.r, source.r)
|
# result.r = blend(backdrop.r, source.r)
|
||||||
result.g = blend(backdrop.g, source.g)
|
# result.g = blend(backdrop.g, source.g)
|
||||||
result.b = blend(backdrop.b, source.b)
|
# result.b = blend(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendLightenFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendLightenFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = max(backdrop.r, source.r)
|
# result.r = max(backdrop.r, source.r)
|
||||||
result.g = max(backdrop.g, source.g)
|
# result.g = max(backdrop.g, source.g)
|
||||||
result.b = max(backdrop.b, source.b)
|
# result.b = max(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendScreenFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendScreenFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = screen(backdrop.r, source.r)
|
# result.r = screen(backdrop.r, source.r)
|
||||||
result.g = screen(backdrop.g, source.g)
|
# result.g = screen(backdrop.g, source.g)
|
||||||
result.b = screen(backdrop.b, source.b)
|
# result.b = screen(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendLinearDodgeFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendLinearDodgeFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = backdrop.r + source.r
|
# result.r = backdrop.r + source.r
|
||||||
result.g = backdrop.g + source.g
|
# result.g = backdrop.g + source.g
|
||||||
result.b = backdrop.b + source.b
|
# result.b = backdrop.b + source.b
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendColorDodgeFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendColorDodgeFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
proc blend(backdrop, source: float32): float32 {.inline.} =
|
# proc blend(backdrop, source: float32): float32 {.inline.} =
|
||||||
if backdrop == 0:
|
# if backdrop == 0:
|
||||||
0.0
|
# 0.0
|
||||||
elif source == 1:
|
# elif source == 1:
|
||||||
1.0
|
# 1.0
|
||||||
else:
|
# else:
|
||||||
min(1, backdrop / (1 - source))
|
# min(1, backdrop / (1 - source))
|
||||||
result.r = blend(backdrop.r, source.r)
|
# result.r = blend(backdrop.r, source.r)
|
||||||
result.g = blend(backdrop.g, source.g)
|
# result.g = blend(backdrop.g, source.g)
|
||||||
result.b = blend(backdrop.b, source.b)
|
# result.b = blend(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendOverlayFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendOverlayFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = hardLight(source.r, backdrop.r)
|
# result.r = hardLight(source.r, backdrop.r)
|
||||||
result.g = hardLight(source.g, backdrop.g)
|
# result.g = hardLight(source.g, backdrop.g)
|
||||||
result.b = hardLight(source.b, backdrop.b)
|
# result.b = hardLight(source.b, backdrop.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendHardLightFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendHardLightFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = hardLight(backdrop.r, source.r)
|
# result.r = hardLight(backdrop.r, source.r)
|
||||||
result.g = hardLight(backdrop.g, source.g)
|
# result.g = hardLight(backdrop.g, source.g)
|
||||||
result.b = hardLight(backdrop.b, source.b)
|
# result.b = hardLight(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendSoftLightFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendSoftLightFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = softLight(backdrop.r, source.r)
|
# result.r = softLight(backdrop.r, source.r)
|
||||||
result.g = softLight(backdrop.g, source.g)
|
# result.g = softLight(backdrop.g, source.g)
|
||||||
result.b = softLight(backdrop.b, source.b)
|
# result.b = softLight(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendDifferenceFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendDifferenceFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result.r = abs(backdrop.r - source.r)
|
# result.r = abs(backdrop.r - source.r)
|
||||||
result.g = abs(backdrop.g - source.g)
|
# result.g = abs(backdrop.g - source.g)
|
||||||
result.b = abs(backdrop.b - source.b)
|
# result.b = abs(backdrop.b - source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendExclusionFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendExclusionFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
proc blend(backdrop, source: float32): float32 {.inline.} =
|
# proc blend(backdrop, source: float32): float32 {.inline.} =
|
||||||
backdrop + source - 2 * backdrop * source
|
# backdrop + source - 2 * backdrop * source
|
||||||
result.r = blend(backdrop.r, source.r)
|
# result.r = blend(backdrop.r, source.r)
|
||||||
result.g = blend(backdrop.g, source.g)
|
# result.g = blend(backdrop.g, source.g)
|
||||||
result.b = blend(backdrop.b, source.b)
|
# result.b = blend(backdrop.b, source.b)
|
||||||
result = alphaFix(backdrop, source, result)
|
# result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendColorFloats*(backdrop, source: Color): Color {.inline.} =
|
proc blendColorFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = SetLum(source, Lum(backdrop))
|
result = SetLum(source, Lum(backdrop))
|
||||||
|
@ -245,24 +403,24 @@ proc blendSaturationFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
|
result = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
|
||||||
result = alphaFix(backdrop, source, result)
|
result = alphaFix(backdrop, source, result)
|
||||||
|
|
||||||
proc blendMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = backdrop
|
# result = backdrop
|
||||||
result.a = min(backdrop.a, source.a)
|
# result.a = min(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendSubtractMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendSubtractMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = backdrop
|
# result = backdrop
|
||||||
result.a = backdrop.a * (1 - source.a)
|
# result.a = backdrop.a * (1 - source.a)
|
||||||
|
|
||||||
proc blendIntersectMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendIntersectMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = backdrop
|
# result = backdrop
|
||||||
result.a = backdrop.a * source.a
|
# result.a = backdrop.a * source.a
|
||||||
|
|
||||||
proc blendExcludeMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendExcludeMaskFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
result = backdrop
|
# result = backdrop
|
||||||
result.a = abs(backdrop.a - source.a)
|
# result.a = abs(backdrop.a - source.a)
|
||||||
|
|
||||||
proc blendOverwriteFloats*(backdrop, source: Color): Color {.inline.} =
|
# proc blendOverwriteFloats*(backdrop, source: Color): Color {.inline.} =
|
||||||
source
|
# source
|
||||||
|
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
when defined(amd64) and not defined(pixieNoSimd):
|
||||||
proc alphaFix(backdrop, source: ColorRGBA, vb, vs, vm: M128): ColorRGBA =
|
proc alphaFix(backdrop, source: ColorRGBA, vb, vs, vm: M128): ColorRGBA =
|
||||||
|
@ -319,95 +477,81 @@ else:
|
||||||
result.b = (b div a div 255).uint8
|
result.b = (b div a div 255).uint8
|
||||||
result.a = a.uint8
|
result.a = a.uint8
|
||||||
|
|
||||||
proc min(a, b: uint32): uint32 {.inline.} =
|
|
||||||
if a < b: a else: b
|
|
||||||
|
|
||||||
proc screen(backdrop, source: uint32): uint8 {.inline.} =
|
|
||||||
(255 - ((255 - backdrop) * (255 - source)) div 255).uint8
|
|
||||||
|
|
||||||
proc hardLight(backdrop, source: uint32): uint8 {.inline.} =
|
|
||||||
if source <= 127:
|
|
||||||
((backdrop * 2 * source) div 255).uint8
|
|
||||||
else:
|
|
||||||
screen(backdrop, 2 * source - 255)
|
|
||||||
|
|
||||||
proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = source
|
blendNormalPremultiplied(
|
||||||
result = alphaFix(backdrop, source, result)
|
backdrop.toPremultipliedAlpha(),
|
||||||
|
source.toPremultipliedAlpha()
|
||||||
|
).toStraightAlpha()
|
||||||
|
|
||||||
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = min(backdrop.r, source.r)
|
let
|
||||||
result.g = min(backdrop.g, source.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = min(backdrop.b, source.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendDarkenPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = ((backdrop.r.uint32 * source.r) div 255).uint8
|
let
|
||||||
result.g = ((backdrop.g.uint32 * source.g) div 255).uint8
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = ((backdrop.b.uint32 * source.b) div 255).uint8
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendMultiplyPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = min(0, backdrop.r.int16 + source.r.int16 - 255).uint8
|
let
|
||||||
result.g = min(0, backdrop.g.int16 + source.g.int16 - 255).uint8
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = min(0, backdrop.b.int16 + source.b.int16 - 255).uint8
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendLinearBurnPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
let
|
||||||
if backdrop == 255:
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
255.uint8
|
source = source.toPremultipliedAlpha()
|
||||||
elif source == 0:
|
result = blendColorBurnPremultiplied(backdrop, source)
|
||||||
0
|
result = result.toStraightAlpha()
|
||||||
else:
|
|
||||||
255 - min(255, (255 * (255 - backdrop)) div source).uint8
|
|
||||||
result.r = blend(backdrop.r, source.r)
|
|
||||||
result.g = blend(backdrop.g, source.g)
|
|
||||||
result.b = blend(backdrop.b, source.b)
|
|
||||||
result = alphaFix(backdrop, source, result)
|
|
||||||
|
|
||||||
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = max(backdrop.r, source.r)
|
let
|
||||||
result.g = max(backdrop.g, source.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = max(backdrop.b, source.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendLightenPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = screen(backdrop.r, source.r)
|
let
|
||||||
result.g = screen(backdrop.g, source.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = screen(backdrop.b, source.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendScreenPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = min(backdrop.r.uint32 + source.r, 255).uint8
|
let
|
||||||
result.g = min(backdrop.g.uint32 + source.g, 255).uint8
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = min(backdrop.b.uint32 + source.b, 255).uint8
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendLinearDodgePremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
let
|
||||||
if backdrop == 0:
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
0.uint8
|
source = source.toPremultipliedAlpha()
|
||||||
elif source == 255:
|
result = blendColorDodgePremultiplied(backdrop, source)
|
||||||
255
|
result = result.toStraightAlpha()
|
||||||
else:
|
|
||||||
min(255, (255 * backdrop) div (255 - source)).uint8
|
|
||||||
result.r = blend(backdrop.r, source.r)
|
|
||||||
result.g = blend(backdrop.g, source.g)
|
|
||||||
result.b = blend(backdrop.b, source.b)
|
|
||||||
result = alphaFix(backdrop, source, result)
|
|
||||||
|
|
||||||
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = hardLight(source.r, backdrop.r)
|
let
|
||||||
result.g = hardLight(source.g, backdrop.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = hardLight(source.b, backdrop.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendOverlayPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = hardLight(backdrop.r, source.r)
|
let
|
||||||
result.g = hardLight(backdrop.g, source.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = hardLight(backdrop.b, source.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendHardLightyPremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
|
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
|
||||||
|
@ -435,18 +579,18 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
blendSoftLightFloats(backdrop.color, source.color).rgba
|
blendSoftLightFloats(backdrop.color, source.color).rgba
|
||||||
|
|
||||||
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.r = max(backdrop.r, source.r) - min(backdrop.r, source.r)
|
let
|
||||||
result.g = max(backdrop.g, source.g) - min(backdrop.g, source.g)
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.b = max(backdrop.b, source.b) - min(backdrop.b, source.b)
|
source = source.toPremultipliedAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
result = blendDifferencePremultiplied(backdrop, source)
|
||||||
|
result = result.toStraightAlpha()
|
||||||
|
|
||||||
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
proc blend(backdrop, source: int32): uint8 {.inline.} =
|
let
|
||||||
max(0, backdrop + source - (2 * backdrop * source) div 255).uint8
|
backdrop = backdrop.toPremultipliedAlpha()
|
||||||
result.r = blend(backdrop.r.int32, source.r.int32)
|
source = source.toPremultipliedAlpha()
|
||||||
result.g = blend(backdrop.g.int32, source.g.int32)
|
result = blendExclusionPremultiplied(backdrop, source)
|
||||||
result.b = blend(backdrop.b.int32, source.b.int32)
|
result = result.toStraightAlpha()
|
||||||
result = alphaFix(backdrop, source, result)
|
|
||||||
|
|
||||||
proc blendColor(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendColor(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
blendColorFloats(backdrop.color, source.color).rgba
|
blendColorFloats(backdrop.color, source.color).rgba
|
||||||
|
@ -466,7 +610,7 @@ proc blendMask(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
|
|
||||||
proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = backdrop
|
result = backdrop
|
||||||
result.a = max(0, (backdrop.a.int32 * (255 - source.a.int32)) div 255).uint8
|
result.a = max(0, (backdrop.a.uint32 * (255 - source.a.uint32)) div 255).uint8
|
||||||
|
|
||||||
proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = backdrop
|
result = backdrop
|
||||||
|
@ -479,7 +623,7 @@ proc blendExcludeMask(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
proc blendOverwrite(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendOverwrite(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
source
|
source
|
||||||
|
|
||||||
proc mixer*(blendMode: BlendMode): Mixer =
|
proc blender*(blendMode: BlendMode): Blender =
|
||||||
case blendMode
|
case blendMode
|
||||||
of bmNormal: blendNormal
|
of bmNormal: blendNormal
|
||||||
of bmDarken: blendDarken
|
of bmDarken: blendDarken
|
||||||
|
@ -504,55 +648,3 @@ proc mixer*(blendMode: BlendMode): Mixer =
|
||||||
of bmSubtractMask: blendSubtractMask
|
of bmSubtractMask: blendSubtractMask
|
||||||
of bmIntersectMask: blendIntersectMask
|
of bmIntersectMask: blendIntersectMask
|
||||||
of bmExcludeMask: blendExcludeMask
|
of bmExcludeMask: blendExcludeMask
|
||||||
|
|
||||||
when defined(release):
|
|
||||||
{.push checks: off.}
|
|
||||||
|
|
||||||
proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline.} =
|
|
||||||
if backdrop.a == 0:
|
|
||||||
return source
|
|
||||||
if source.a == 255:
|
|
||||||
return source
|
|
||||||
if source.a == 0:
|
|
||||||
return backdrop
|
|
||||||
|
|
||||||
let k = (255 - source.a.uint32)
|
|
||||||
result.r = source.r + ((backdrop.r.uint32 * k) div 255).uint8
|
|
||||||
result.g = source.g + ((backdrop.g.uint32 * k) div 255).uint8
|
|
||||||
result.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
|
|
||||||
result.a = source.a + ((backdrop.a.uint32 * k) div 255).uint8
|
|
||||||
|
|
||||||
when defined(amd64) and not defined(pixieNoSimd):
|
|
||||||
proc blendNormalPremultiplied*(backdrop, source: M128i): M128i {.inline.} =
|
|
||||||
let
|
|
||||||
alphaMask = mm_set1_epi32(cast[int32](0xff000000))
|
|
||||||
oddMask = mm_set1_epi16(cast[int16](0xff00))
|
|
||||||
div255 = mm_set1_epi16(cast[int16](0x8081))
|
|
||||||
|
|
||||||
# Shortcuts didn't help (backdrop.a == 0, source.a == 0, source.a == 255)
|
|
||||||
|
|
||||||
var
|
|
||||||
sourceAlpha = mm_and_si128(source, alphaMask)
|
|
||||||
backdropEven = mm_slli_epi16(backdrop, 8)
|
|
||||||
backdropOdd = mm_and_si128(backdrop, oddMask)
|
|
||||||
|
|
||||||
sourceAlpha = mm_or_si128(sourceAlpha, mm_srli_epi32(sourceAlpha, 16))
|
|
||||||
|
|
||||||
let k = mm_sub_epi32(
|
|
||||||
mm_set1_epi32(cast[int32]([0.uint8, 255, 0, 255])),
|
|
||||||
sourceAlpha
|
|
||||||
)
|
|
||||||
|
|
||||||
backdropEven = mm_mulhi_epu16(backdropEven, k)
|
|
||||||
backdropOdd = mm_mulhi_epu16(backdropOdd, k)
|
|
||||||
|
|
||||||
backdropEven = mm_srli_epi16(mm_mulhi_epu16(backdropEven, div255), 7)
|
|
||||||
backdropOdd = mm_srli_epi16(mm_mulhi_epu16(backdropOdd, div255), 7)
|
|
||||||
|
|
||||||
mm_add_epi8(
|
|
||||||
source,
|
|
||||||
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
|
|
||||||
)
|
|
||||||
|
|
||||||
when defined(release):
|
|
||||||
{.pop.}
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ proc lerp*(a, b: ColorRGBA, t: float32): ColorRGBA {.inline.} =
|
||||||
|
|
||||||
proc toPremultipliedAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
proc toPremultipliedAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
||||||
## Converts a color to premultiplied alpha from straight alpha.
|
## Converts a color to premultiplied alpha from straight alpha.
|
||||||
result.r = ((c.r.uint16 * c.a.uint16) div 255).uint8
|
result.r = ((c.r.uint32 * c.a.uint32) div 255).uint8
|
||||||
result.g = ((c.g.uint16 * c.a.uint16) div 255).uint8
|
result.g = ((c.g.uint32 * c.a.uint32) div 255).uint8
|
||||||
result.b = ((c.b.uint16 * c.a.uint16) div 255).uint8
|
result.b = ((c.b.uint32 * c.a.uint32) div 255).uint8
|
||||||
result.a = c.a
|
result.a = c.a
|
||||||
|
|
||||||
proc toStraightAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
proc toStraightAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
|
||||||
|
|
|
@ -387,7 +387,7 @@ proc drawCorrect*(a, b: Image, mat: Mat3, blendMode: BlendMode) =
|
||||||
minFilterBy2 /= 2
|
minFilterBy2 /= 2
|
||||||
matInv = matInv * scale(vec2(0.5, 0.5))
|
matInv = matInv * scale(vec2(0.5, 0.5))
|
||||||
|
|
||||||
let mixer = blendMode.mixer()
|
let blender = blendMode.blender()
|
||||||
for y in 0 ..< a.height:
|
for y in 0 ..< a.height:
|
||||||
for x in 0 ..< a.width:
|
for x in 0 ..< a.width:
|
||||||
let
|
let
|
||||||
|
@ -396,7 +396,7 @@ proc drawCorrect*(a, b: Image, mat: Mat3, blendMode: BlendMode) =
|
||||||
yFloat = srcPos.y - h
|
yFloat = srcPos.y - h
|
||||||
rgba = a.getRgbaUnsafe(x, y)
|
rgba = a.getRgbaUnsafe(x, y)
|
||||||
rgba2 = b.getRgbaSmooth(xFloat, yFloat)
|
rgba2 = b.getRgbaSmooth(xFloat, yFloat)
|
||||||
a.setRgbaUnsafe(x, y, mixer(rgba, rgba2))
|
a.setRgbaUnsafe(x, y, blender(rgba, rgba2))
|
||||||
|
|
||||||
proc drawUber(
|
proc drawUber(
|
||||||
a, b: Image,
|
a, b: Image,
|
||||||
|
@ -405,7 +405,7 @@ proc drawUber(
|
||||||
blendMode: BlendMode,
|
blendMode: BlendMode,
|
||||||
smooth: bool
|
smooth: bool
|
||||||
) =
|
) =
|
||||||
let mixer = blendMode.mixer()
|
let blender = blendMode.blender()
|
||||||
for y in 0 ..< a.height:
|
for y in 0 ..< a.height:
|
||||||
var
|
var
|
||||||
xMin = a.width
|
xMin = a.width
|
||||||
|
@ -439,7 +439,7 @@ proc drawUber(
|
||||||
b.getRgbaSmooth(xFloat, yFloat)
|
b.getRgbaSmooth(xFloat, yFloat)
|
||||||
else:
|
else:
|
||||||
b.getRgbaUnsafe(xFloat.int, yFloat.int)
|
b.getRgbaUnsafe(xFloat.int, yFloat.int)
|
||||||
a.setRgbaUnsafe(x, y, mixer(rgba, rgba2))
|
a.setRgbaUnsafe(x, y, blender(rgba, rgba2))
|
||||||
|
|
||||||
if blendMode == bmIntersectMask:
|
if blendMode == bmIntersectMask:
|
||||||
if a.width - xMax > 0:
|
if a.width - xMax > 0:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import benchy, chroma, vmath, pixie/images
|
import benchy, chroma, pixie/images
|
||||||
|
|
||||||
include pixie/blends
|
include pixie/blends
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ timeIt "blendNormal":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendNormalFloats":
|
# timeIt "blendNormalFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendNormalFloats(
|
# backdrop.data[i] = blendNormalFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendDarken":
|
timeIt "blendDarken":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -32,13 +32,13 @@ timeIt "blendDarken":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendDarkenFloats":
|
# timeIt "blendDarkenFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendDarkenFloats(
|
# backdrop.data[i] = blendDarkenFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendMultiply":
|
timeIt "blendMultiply":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -46,13 +46,13 @@ timeIt "blendMultiply":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendMultiplyFloats":
|
# timeIt "blendMultiplyFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendMultiplyFloats(
|
# backdrop.data[i] = blendMultiplyFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendLinearBurn":
|
timeIt "blendLinearBurn":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -60,13 +60,13 @@ timeIt "blendLinearBurn":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendLinearBurnFloats":
|
# timeIt "blendLinearBurnFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendLinearBurnFloats(
|
# backdrop.data[i] = blendLinearBurnFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendColorBurn":
|
timeIt "blendColorBurn":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -74,13 +74,13 @@ timeIt "blendColorBurn":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendColorBurnFloats":
|
# timeIt "blendColorBurnFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendColorBurnFloats(
|
# backdrop.data[i] = blendColorBurnFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendLighten":
|
timeIt "blendLighten":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -88,13 +88,13 @@ timeIt "blendLighten":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendLightenFloats":
|
# timeIt "blendLightenFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendLightenFloats(
|
# backdrop.data[i] = blendLightenFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendScreen":
|
timeIt "blendScreen":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -102,13 +102,13 @@ timeIt "blendScreen":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendScreenFloats":
|
# timeIt "blendScreenFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendScreenFloats(
|
# backdrop.data[i] = blendScreenFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendLinearDodge":
|
timeIt "blendLinearDodge":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -116,13 +116,13 @@ timeIt "blendLinearDodge":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendLinearDodgeFloats":
|
# timeIt "blendLinearDodgeFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendLinearDodgeFloats(
|
# backdrop.data[i] = blendLinearDodgeFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendColorDodge":
|
timeIt "blendColorDodge":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -130,13 +130,13 @@ timeIt "blendColorDodge":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendColorDodgeFloats":
|
# timeIt "blendColorDodgeFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendColorDodgeFloats(
|
# backdrop.data[i] = blendColorDodgeFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendOverlay":
|
timeIt "blendOverlay":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -144,13 +144,13 @@ timeIt "blendOverlay":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendOverlayFloats":
|
# timeIt "blendOverlayFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendOverlayFloats(
|
# backdrop.data[i] = blendOverlayFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendSoftLight":
|
timeIt "blendSoftLight":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -158,13 +158,13 @@ timeIt "blendSoftLight":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendSoftLightFloats":
|
# timeIt "blendSoftLightFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendSoftLightFloats(
|
# backdrop.data[i] = blendSoftLightFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendHardLight":
|
timeIt "blendHardLight":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -172,13 +172,13 @@ timeIt "blendHardLight":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendHardLightFloats":
|
# timeIt "blendHardLightFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendHardLightFloats(
|
# backdrop.data[i] = blendHardLightFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendDifference":
|
timeIt "blendDifference":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -186,13 +186,13 @@ timeIt "blendDifference":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendDifferenceFloats":
|
# timeIt "blendDifferenceFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendDifferenceFloats(
|
# backdrop.data[i] = blendDifferenceFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendExclusion":
|
timeIt "blendExclusion":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -200,13 +200,13 @@ timeIt "blendExclusion":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendExclusionFloats":
|
# timeIt "blendExclusionFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendExclusionFloats(
|
# backdrop.data[i] = blendExclusionFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendHue":
|
timeIt "blendHue":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -214,13 +214,13 @@ timeIt "blendHue":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendHueFloats":
|
# timeIt "blendHueFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendHueFloats(
|
# backdrop.data[i] = blendHueFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendSaturation":
|
timeIt "blendSaturation":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -228,11 +228,11 @@ timeIt "blendSaturation":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendSaturationFloats":
|
# timeIt "blendSaturationFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendSaturationFloats(
|
# backdrop.data[i] = blendSaturationFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
|
@ -242,13 +242,13 @@ timeIt "blendColor":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendColorFloats":
|
# timeIt "blendColorFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendColorFloats(
|
# backdrop.data[i] = blendColorFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendLuminosity":
|
timeIt "blendLuminosity":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -256,13 +256,13 @@ timeIt "blendLuminosity":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendLuminosityFloats":
|
# timeIt "blendLuminosityFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendLuminosityFloats(
|
# backdrop.data[i] = blendLuminosityFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendMask":
|
timeIt "blendMask":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -270,13 +270,13 @@ timeIt "blendMask":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendMaskFloats":
|
# timeIt "blendMaskFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendMaskFloats(
|
# backdrop.data[i] = blendMaskFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendSubtractMask":
|
timeIt "blendSubtractMask":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -284,13 +284,13 @@ timeIt "blendSubtractMask":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendSubtractMaskFloats":
|
# timeIt "blendSubtractMaskFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendSubtractMaskFloats(
|
# backdrop.data[i] = blendSubtractMaskFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendIntersectMask":
|
timeIt "blendIntersectMask":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -298,13 +298,13 @@ timeIt "blendIntersectMask":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendIntersectMaskFloats":
|
# timeIt "blendIntersectMaskFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendIntersectMaskFloats(
|
# backdrop.data[i] = blendIntersectMaskFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendExcludeMask":
|
timeIt "blendExcludeMask":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
@ -312,13 +312,13 @@ timeIt "blendExcludeMask":
|
||||||
|
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
timeIt "blendExcludeMaskFloats":
|
# timeIt "blendExcludeMaskFloats":
|
||||||
for i in 0 ..< backdrop.data.len:
|
# for i in 0 ..< backdrop.data.len:
|
||||||
backdrop.data[i] = blendExcludeMaskFloats(
|
# backdrop.data[i] = blendExcludeMaskFloats(
|
||||||
backdrop.data[i].color, source.data[i].color
|
# backdrop.data[i].color, source.data[i].color
|
||||||
).rgba
|
# ).rgba
|
||||||
|
|
||||||
reset()
|
# reset()
|
||||||
|
|
||||||
timeIt "blendNormalPremultiplied":
|
timeIt "blendNormalPremultiplied":
|
||||||
for i in 0 ..< backdrop.data.len:
|
for i in 0 ..< backdrop.data.len:
|
||||||
|
|
Loading…
Reference in a new issue