From a801e9d3598c679cf422f0619c6d428d90dc1811 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Sat, 30 Jan 2021 16:25:38 -0600 Subject: [PATCH] Revert "premultiplied blends for most" This reverts commit 052e114db1f2878c213bb6eba5b65b82fc445f81. --- src/pixie/blends.nim | 246 ++++++++++++++----------------------------- 1 file changed, 78 insertions(+), 168 deletions(-) diff --git a/src/pixie/blends.nim b/src/pixie/blends.nim index 61a6a4f..255db39 100644 --- a/src/pixie/blends.nim +++ b/src/pixie/blends.nim @@ -39,24 +39,6 @@ type 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 @@ -69,95 +51,7 @@ proc blendNormalPremultiplied*(backdrop, source: ColorRGBA): ColorRGBA {.inline. 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) + 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.} = @@ -477,6 +371,18 @@ else: result.b = (b div a div 255).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 = blendNormalPremultiplied( backdrop.toPremultipliedAlpha(), @@ -484,74 +390,78 @@ proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA = ).toStraightAlpha() proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendDarkenPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = min(backdrop.r, source.r) + result.g = min(backdrop.g, source.g) + result.b = min(backdrop.b, source.b) + result = alphaFix(backdrop, source, result) proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendMultiplyPremultiplied(backdrop, source) - result = result.toStraightAlpha() + 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 = alphaFix(backdrop, source, result) proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendLinearBurnPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = min(0, backdrop.r.int16 + source.r.int16 - 255).uint8 + result.g = min(0, backdrop.g.int16 + source.g.int16 - 255).uint8 + result.b = min(0, backdrop.b.int16 + source.b.int16 - 255).uint8 + result = alphaFix(backdrop, source, result) proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendColorBurnPremultiplied(backdrop, source) - result = result.toStraightAlpha() + 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 = alphaFix(backdrop, source, result) proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendLightenPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = max(backdrop.r, source.r) + result.g = max(backdrop.g, source.g) + result.b = max(backdrop.b, source.b) + result = alphaFix(backdrop, source, result) proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendScreenPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = screen(backdrop.r, source.r) + result.g = screen(backdrop.g, source.g) + result.b = screen(backdrop.b, source.b) + result = alphaFix(backdrop, source, result) proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendLinearDodgePremultiplied(backdrop, source) - result = result.toStraightAlpha() + 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 = alphaFix(backdrop, source, result) proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendColorDodgePremultiplied(backdrop, source) - result = result.toStraightAlpha() + 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 = alphaFix(backdrop, source, result) proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendOverlayPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = hardLight(source.r, backdrop.r) + result.g = hardLight(source.g, backdrop.g) + result.b = hardLight(source.b, backdrop.b) + result = alphaFix(backdrop, source, result) proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendHardLightyPremultiplied(backdrop, source) - result = result.toStraightAlpha() + result.r = hardLight(backdrop.r, source.r) + result.g = hardLight(backdrop.g, source.g) + result.b = hardLight(backdrop.b, source.b) + result = alphaFix(backdrop, source, result) proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA = # proc softLight(backdrop, source: int32): uint8 {.inline.} = @@ -579,18 +489,18 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA = blendSoftLightFloats(backdrop.color, source.color).rgba proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendDifferencePremultiplied(backdrop, source) - result = result.toStraightAlpha() + 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 = alphaFix(backdrop, source, result) proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA = - let - backdrop = backdrop.toPremultipliedAlpha() - source = source.toPremultipliedAlpha() - result = blendExclusionPremultiplied(backdrop, source) - result = result.toStraightAlpha() + proc blend(backdrop, source: int32): uint8 {.inline.} = + max(0, backdrop + source - (2 * backdrop * source) div 255).uint8 + result.r = blend(backdrop.r.int32, source.r.int32) + result.g = blend(backdrop.g.int32, source.g.int32) + result.b = blend(backdrop.b.int32, source.b.int32) + result = alphaFix(backdrop, source, result) proc blendColor(backdrop, source: ColorRGBA): ColorRGBA = blendColorFloats(backdrop.color, source.color).rgba @@ -610,7 +520,7 @@ proc blendMask(backdrop, source: ColorRGBA): ColorRGBA = proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA = 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 = result = backdrop