Merge pull request #86 from guzba/master

revert blend stuff
This commit is contained in:
treeform 2021-01-30 18:41:15 -08:00 committed by GitHub
commit 6bb389c071
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 317 additions and 426 deletions

View file

@ -39,40 +39,6 @@ type
when defined(release): when defined(release):
{.push checks: off.} {.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 tripleBlend(result: var ColorRGBA, backdrop, source: ColorRGBA) =
result.a = blendAlpha(backdrop.a, source.a)
if result.a == 0:
result = rgba(0, 0, 0, 0)
else:
let
t0 = (255 - backdrop.a.uint32) * source.a.uint32
t1 = (255 - source.a.uint32) * backdrop.a.uint32
t2 = 255.uint32 * 255
r = t0 * source.r + t1 * backdrop.r + t2 * result.r
g = t0 * source.g + t1 * backdrop.g + t2 * result.g
b = t0 * source.b + t1 * backdrop.b + t2 * result.b
result.r = (r div 255 div result.a).uint8
result.g = (g div 255 div result.a).uint8
result.b = (b div 255 div result.a).uint8
proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline.} = proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline.} =
if backdrop.a == 0: if backdrop.a == 0:
return source return source
@ -85,95 +51,7 @@ proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline.
result.r = source.r + ((backdrop.r.uint32 * k) div 255).uint8 result.r = source.r + ((backdrop.r.uint32 * k) div 255).uint8
result.g = source.g + ((backdrop.g.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.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
result.a = blendAlpha(backdrop.a, source.a) result.a = source.a + ((backdrop.a.uint32 * k) div 255).uint8
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.tripleBlend(backdrop, source)
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.tripleBlend(backdrop, source)
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.tripleBlend(backdrop, source)
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): when defined(amd64) and not defined(pixieNoSimd):
proc blendNormalPremultiplied*(backdrop, source: M128i): M128i {.inline.} = proc blendNormalPremultiplied*(backdrop, source: M128i): M128i {.inline.} =
@ -246,14 +124,14 @@ 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
@ -305,83 +183,83 @@ 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)
@ -389,19 +267,19 @@ proc blendSoftLightFloats*(backdrop, source: Color): Color {.inline.} =
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))
@ -419,24 +297,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 =
@ -493,6 +371,18 @@ 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 =
blendNormalPremultiplied( blendNormalPremultiplied(
backdrop.toPremultipliedAlpha(), backdrop.toPremultipliedAlpha(),
@ -500,76 +390,87 @@ proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
).toStraightAlpha() ).toStraightAlpha()
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA = proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = min(backdrop.r, source.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = min(backdrop.g, source.g)
source = source.toPremultipliedAlpha() result.b = min(backdrop.b, source.b)
result = blendDarkenPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA = proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = ((backdrop.r.uint32 * source.r) div 255).uint8
backdrop = backdrop.toPremultipliedAlpha() result.g = ((backdrop.g.uint32 * source.g) div 255).uint8
source = source.toPremultipliedAlpha() result.b = ((backdrop.b.uint32 * source.b) div 255).uint8
result = blendMultiplyPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA = proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = min(0, backdrop.r.int16 + source.r.int16 - 255).uint8
backdrop = backdrop.toPremultipliedAlpha() result.g = min(0, backdrop.g.int16 + source.g.int16 - 255).uint8
source = source.toPremultipliedAlpha() result.b = min(0, backdrop.b.int16 + source.b.int16 - 255).uint8
result = blendLinearBurnPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA = proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
let proc blend(backdrop, source: uint32): uint8 {.inline.} =
backdrop = backdrop.toPremultipliedAlpha() if backdrop == 255:
source = source.toPremultipliedAlpha() 255.uint8
result = blendColorBurnPremultiplied(backdrop, source) elif source == 0:
result = result.toStraightAlpha() 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 = alphaFix(backdrop, source, result)
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA = proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = max(backdrop.r, source.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = max(backdrop.g, source.g)
source = source.toPremultipliedAlpha() result.b = max(backdrop.b, source.b)
result = blendLightenPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA = proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = screen(backdrop.r, source.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = screen(backdrop.g, source.g)
source = source.toPremultipliedAlpha() result.b = screen(backdrop.b, source.b)
result = blendScreenPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA = proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = min(backdrop.r.uint32 + source.r, 255).uint8
backdrop = backdrop.toPremultipliedAlpha() result.g = min(backdrop.g.uint32 + source.g, 255).uint8
source = source.toPremultipliedAlpha() result.b = min(backdrop.b.uint32 + source.b, 255).uint8
result = blendLinearDodgePremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA = proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
let proc blend(backdrop, source: uint32): uint8 {.inline.} =
backdrop = backdrop.toPremultipliedAlpha() if backdrop == 0:
source = source.toPremultipliedAlpha() 0.uint8
result = blendColorDodgePremultiplied(backdrop, source) elif source == 255:
result = result.toStraightAlpha() 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 = alphaFix(backdrop, source, result)
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA = proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = hardLight(source.r, backdrop.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = hardLight(source.g, backdrop.g)
source = source.toPremultipliedAlpha() result.b = hardLight(source.b, backdrop.b)
result = blendOverlayPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA = proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = hardLight(backdrop.r, source.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = hardLight(backdrop.g, source.g)
source = source.toPremultipliedAlpha() result.b = hardLight(backdrop.b, source.b)
result = blendHardLightyPremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA = proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
# ## Pegtop
# (
# ((255 - 2 * source) * backdrop ^ 2) div 255 ^ 2 +
# (2 * source * backdrop) div 255
# ).uint8
when defined(amd64) and not defined(pixieNoSimd): when defined(amd64) and not defined(pixieNoSimd):
let let
vb = mm_setr_ps(backdrop.r.float32, backdrop.g.float32, backdrop.b.float32, 0) vb = mm_setr_ps(backdrop.r.float32, backdrop.g.float32, backdrop.b.float32, 0)
@ -586,30 +487,20 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
result = alphaFix(backdrop, source, vb, vs, vm) result = alphaFix(backdrop, source, vb, vs, vm)
else: else:
blendSoftLightFloats(backdrop.color, source.color).rgba blendSoftLightFloats(backdrop.color, source.color).rgba
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
# ## Pegtop
# (
# ((255 - 2 * source) * (backdrop ^ 2)) div (255 ^ 2) +
# (2 * source * backdrop) div 255
# ).uint8
# result.r = softLight(backdrop.r.int32, source.r.int32)
# result.g = softLight(backdrop.g.int32, source.g.int32)
# result.b = softLight(backdrop.b.int32, source.b.int32)
# result = alphaFix(backdrop, source, result)
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA = proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
let result.r = max(backdrop.r, source.r) - min(backdrop.r, source.r)
backdrop = backdrop.toPremultipliedAlpha() result.g = max(backdrop.g, source.g) - min(backdrop.g, source.g)
source = source.toPremultipliedAlpha() result.b = max(backdrop.b, source.b) - min(backdrop.b, source.b)
result = blendDifferencePremultiplied(backdrop, source) result = alphaFix(backdrop, source, result)
result = result.toStraightAlpha()
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA = proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
let proc blend(backdrop, source: int32): uint8 {.inline.} =
backdrop = backdrop.toPremultipliedAlpha() max(0, backdrop + source - (2 * backdrop * source) div 255).uint8
source = source.toPremultipliedAlpha() result.r = blend(backdrop.r.int32, source.r.int32)
result = blendExclusionPremultiplied(backdrop, source) result.g = blend(backdrop.g.int32, source.g.int32)
result = result.toStraightAlpha() result.b = blend(backdrop.b.int32, source.b.int32)
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
@ -629,7 +520,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.uint32 * (255 - source.a.uint32)) div 255).uint8 result.a = max(0, (backdrop.a.int32 * (255 - source.a.int32)) div 255).uint8
proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA = proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
result = backdrop result = backdrop

View file

@ -1,4 +1,4 @@
import benchy, chroma, pixie/images import benchy, chroma, vmath, 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: