Merge pull request #101 from guzba/master
several blends with premul alpha directly
This commit is contained in:
commit
a7cb277d4f
1 changed files with 74 additions and 61 deletions
|
@ -29,7 +29,7 @@ type
|
||||||
bmLuminosity
|
bmLuminosity
|
||||||
|
|
||||||
bmMask ## Special blend mode that is used for masking
|
bmMask ## Special blend mode that is used for masking
|
||||||
bmOverwrite ## Special that does not blend but copies the pixels from target.
|
bmOverwrite ## Special blend mode that just copies pixels
|
||||||
bmSubtractMask ## Inverse mask
|
bmSubtractMask ## Inverse mask
|
||||||
bmIntersectMask
|
bmIntersectMask
|
||||||
bmExcludeMask
|
bmExcludeMask
|
||||||
|
@ -87,13 +87,19 @@ proc blendAlpha*(backdrop, source: uint8): uint8 {.inline.} =
|
||||||
source + ((backdrop.uint32 * (255 - source)) div 255).uint8
|
source + ((backdrop.uint32 * (255 - source)) div 255).uint8
|
||||||
|
|
||||||
proc screen(backdrop, source: uint32): uint8 {.inline.} =
|
proc screen(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
(255 - ((255 - backdrop) * (255 - source)) div 255).uint8
|
((backdrop + source).int32 - ((backdrop * source) div 255).int32).uint8
|
||||||
|
|
||||||
proc hardLight(backdrop, source: uint32): uint8 {.inline.} =
|
proc hardLight(
|
||||||
if source <= 127:
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint32
|
||||||
((backdrop * 2 * source) div 255).uint8
|
): uint8 {.inline.} =
|
||||||
|
if sourceColor * 2 <= sourceAlpha:
|
||||||
|
((
|
||||||
|
2 * sourceColor * backdropColor +
|
||||||
|
(sourceColor * (255 - backdropAlpha)) +
|
||||||
|
(backdropColor * (255 - sourceAlpha))
|
||||||
|
) div 255).uint8
|
||||||
else:
|
else:
|
||||||
screen(backdrop, 2 * source - 255)
|
screen(backdropColor, sourceColor)
|
||||||
|
|
||||||
proc softLight(backdrop, source: float32): float32 {.inline.} =
|
proc softLight(backdrop, source: float32): float32 {.inline.} =
|
||||||
## Pegtop
|
## Pegtop
|
||||||
|
@ -169,24 +175,33 @@ proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result.a = blendAlpha(backdrop.a, source.a)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
proc blend(
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
source = source.toStraightAlpha()
|
): uint8 {.inline.} =
|
||||||
result.r = min(backdrop.r, source.r)
|
min(
|
||||||
result.g = min(backdrop.g, source.g)
|
backdropColor + ((255 - backdropAlpha).uint32 * sourceColor) div 255,
|
||||||
result.b = min(backdrop.b, source.b)
|
sourceColor + ((255 - sourceAlpha).uint32 * backdropColor) div 255
|
||||||
result = alphaFix(backdrop, source, result)
|
).uint8
|
||||||
result = result.toPremultipliedAlpha()
|
|
||||||
|
result.r = blend(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
|
result.g = blend(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
proc blend(
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
source = source.toStraightAlpha()
|
): uint8 {.inline.} =
|
||||||
result.r = ((backdrop.r.uint32 * source.r) div 255).uint8
|
((
|
||||||
result.g = ((backdrop.g.uint32 * source.g) div 255).uint8
|
(255 - backdropAlpha).uint32 * sourceColor +
|
||||||
result.b = ((backdrop.b.uint32 * source.b) div 255).uint8
|
(255 - sourceAlpha).uint32 * backdropColor +
|
||||||
result = alphaFix(backdrop, source, result)
|
backdropColor.uint32 * sourceColor
|
||||||
result = result.toPremultipliedAlpha()
|
) div 255).uint8
|
||||||
|
|
||||||
|
result.r = blend(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
|
result.g = blend(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
let
|
||||||
|
@ -216,24 +231,24 @@ proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = result.toPremultipliedAlpha()
|
result = result.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
proc blend(
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
source = source.toStraightAlpha()
|
): uint8 {.inline.} =
|
||||||
result.r = max(backdrop.r, source.r)
|
max(
|
||||||
result.g = max(backdrop.g, source.g)
|
backdropColor + ((255 - backdropAlpha).uint32 * sourceColor) div 255,
|
||||||
result.b = max(backdrop.b, source.b)
|
sourceColor + ((255 - sourceAlpha).uint32 * backdropColor) div 255
|
||||||
result = alphaFix(backdrop, source, result)
|
).uint8
|
||||||
result = result.toPremultipliedAlpha()
|
|
||||||
|
result.r = blend(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
|
result.g = blend(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
|
||||||
backdrop = backdrop.toStraightAlpha()
|
|
||||||
source = source.toStraightAlpha()
|
|
||||||
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.a = blendAlpha(backdrop.a, source.a)
|
||||||
result = result.toPremultipliedAlpha()
|
|
||||||
|
|
||||||
proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
let
|
||||||
|
@ -263,14 +278,10 @@ proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = result.toPremultipliedAlpha()
|
result = result.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
result.r = hardLight(source.r, source.a, backdrop.r, backdrop.a)
|
||||||
backdrop = backdrop.toStraightAlpha()
|
result.g = hardLight(source.g, source.a, backdrop.g, backdrop.a)
|
||||||
source = source.toStraightAlpha()
|
result.b = hardLight(source.b, source.a, backdrop.b, backdrop.a)
|
||||||
result.r = hardLight(source.r, backdrop.r)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
result.g = hardLight(source.g, backdrop.g)
|
|
||||||
result.b = hardLight(source.b, backdrop.b)
|
|
||||||
result = alphaFix(backdrop, source, result)
|
|
||||||
result = result.toPremultipliedAlpha()
|
|
||||||
|
|
||||||
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.} =
|
||||||
|
@ -341,24 +352,26 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
result = result.toPremultipliedAlpha()
|
result = result.toPremultipliedAlpha()
|
||||||
|
|
||||||
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
result.r = hardLight(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
backdrop = backdrop.toStraightAlpha()
|
result.g = hardLight(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
source = source.toStraightAlpha()
|
result.b = hardLight(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
result.r = hardLight(backdrop.r, source.r)
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
result.g = hardLight(backdrop.g, source.g)
|
|
||||||
result.b = hardLight(backdrop.b, source.b)
|
|
||||||
result = alphaFix(backdrop, source, result)
|
|
||||||
result = result.toPremultipliedAlpha()
|
|
||||||
|
|
||||||
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
let
|
proc blend(
|
||||||
backdrop = backdrop.toStraightAlpha()
|
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
|
||||||
source = source.toStraightAlpha()
|
): uint8 {.inline.} =
|
||||||
result.r = max(backdrop.r, source.r) - min(backdrop.r, source.r)
|
((backdropColor + sourceColor).int32 - 2 *
|
||||||
result.g = max(backdrop.g, source.g) - min(backdrop.g, source.g)
|
(min(
|
||||||
result.b = max(backdrop.b, source.b) - min(backdrop.b, source.b)
|
backdropColor.uint32 * sourceAlpha,
|
||||||
result = alphaFix(backdrop, source, result)
|
sourceColor.uint32 * backdropAlpha
|
||||||
result = result.toPremultipliedAlpha()
|
) div 255).int32
|
||||||
|
).uint8
|
||||||
|
|
||||||
|
result.r = blend(backdrop.r, backdrop.a, source.r, source.a)
|
||||||
|
result.g = blend(backdrop.g, backdrop.a, source.g, source.a)
|
||||||
|
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
|
||||||
|
result.a = blendAlpha(backdrop.a, source.a)
|
||||||
|
|
||||||
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
|
||||||
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
proc blend(backdrop, source: uint32): uint8 {.inline.} =
|
||||||
|
@ -454,9 +467,9 @@ proc blender*(blendMode: BlendMode): Blender =
|
||||||
of bmIntersectMask: blendIntersectMask
|
of bmIntersectMask: blendIntersectMask
|
||||||
of bmExcludeMask: blendExcludeMask
|
of bmExcludeMask: blendExcludeMask
|
||||||
else:
|
else:
|
||||||
blendWhite
|
# blendWhite
|
||||||
# blendNormal
|
# blendNormal
|
||||||
# raise newException(PixieError, "No blender for " & $blendMode)
|
raise newException(PixieError, "No blender for " & $blendMode)
|
||||||
|
|
||||||
proc maskMask(backdrop, source: uint8): uint8 =
|
proc maskMask(backdrop, source: uint8): uint8 =
|
||||||
((backdrop.uint32 * source) div 255).uint8
|
((backdrop.uint32 * source) div 255).uint8
|
||||||
|
|
Loading…
Reference in a new issue