faster, less code
This commit is contained in:
parent
7b58d4bf9a
commit
9ad9817959
3 changed files with 165 additions and 265 deletions
|
@ -4,31 +4,34 @@ import chroma, math
|
|||
# See https://www.w3.org/TR/compositing-1/
|
||||
# See https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_blend_equation_advanced.txt
|
||||
|
||||
type BlendMode* = enum
|
||||
bmNormal
|
||||
bmDarken
|
||||
bmMultiply
|
||||
bmLinearBurn
|
||||
bmColorBurn
|
||||
bmLighten
|
||||
bmScreen
|
||||
bmLinearDodge
|
||||
bmColorDodge
|
||||
bmOverlay
|
||||
bmSoftLight
|
||||
bmHardLight
|
||||
bmDifference
|
||||
bmExclusion
|
||||
bmHue
|
||||
bmSaturation
|
||||
bmColor
|
||||
bmLuminosity
|
||||
type
|
||||
BlendMode* = enum
|
||||
bmNormal
|
||||
bmDarken
|
||||
bmMultiply
|
||||
bmLinearBurn
|
||||
bmColorBurn
|
||||
bmLighten
|
||||
bmScreen
|
||||
bmLinearDodge
|
||||
bmColorDodge
|
||||
bmOverlay
|
||||
bmSoftLight
|
||||
bmHardLight
|
||||
bmDifference
|
||||
bmExclusion
|
||||
bmHue
|
||||
bmSaturation
|
||||
bmColor
|
||||
bmLuminosity
|
||||
|
||||
bmMask ## Special blend mode that is used for masking
|
||||
bmOverwrite ## Special that does not blend but copies the pixels from target.
|
||||
bmSubtractMask ## Inverse mask
|
||||
bmIntersectMask
|
||||
bmExcludeMask
|
||||
bmMask ## Special blend mode that is used for masking
|
||||
bmOverwrite ## Special that does not blend but copies the pixels from target.
|
||||
bmSubtractMask ## Inverse mask
|
||||
bmIntersectMask
|
||||
bmExcludeMask
|
||||
|
||||
Mixer* = proc(a, b: ColorRGBA): ColorRGBA
|
||||
|
||||
proc `+`*(a, b: Color): Color {.inline.} =
|
||||
result.r = a.r + b.r
|
||||
|
@ -123,202 +126,176 @@ proc alphaFix(Cb, Cs, mixed: Color): Color {.inline.} =
|
|||
result.g /= result.a
|
||||
result.b /= result.a
|
||||
|
||||
proc blendDarken(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendDarkenFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
min(Cb, Cs)
|
||||
|
||||
proc blendMultiply(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendMultiplyFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
Cb * Cs
|
||||
|
||||
proc blendLinearBurn(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendLinearBurnFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
Cb + Cs - 1
|
||||
|
||||
proc blendColorBurn(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendColorBurnFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
if Cb == 1: 1.0
|
||||
elif Cs == 0: 0.0
|
||||
else: 1.0 - min(1, (1 - Cb) / Cs)
|
||||
|
||||
proc blendLighten(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendLightenFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
max(Cb, Cs)
|
||||
|
||||
proc blendScreen(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendScreenFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
screen(Cb, Cs)
|
||||
|
||||
proc blendLinearDodge(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendLinearDodgeFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
Cb + Cs
|
||||
|
||||
proc blendColorDodge(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendColorDodgeFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
if Cb == 0: 0.0
|
||||
elif Cs == 1: 1.0
|
||||
else: min(1, Cb / (1 - Cs))
|
||||
|
||||
proc blendOverlay(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendOverlayFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
hardLight(Cs, Cb)
|
||||
|
||||
proc blendHardLight(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendHardLightFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
hardLight(Cb, Cs)
|
||||
|
||||
proc blendSoftLight(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendSoftLightFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
softLight(Cb, Cs)
|
||||
|
||||
proc blendDifference(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendDifferenceFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
abs(Cb - Cs)
|
||||
|
||||
proc blendExclusion(Cb, Cs: float32): float32 {.inline.} =
|
||||
proc blendExclusionFloat(Cb, Cs: float32): float32 {.inline.} =
|
||||
Cb + Cs - 2 * Cb * Cs
|
||||
|
||||
proc blendNormal(Cb, Cs: Color): Color {.inline.} =
|
||||
proc blendNormalFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = Cs.r
|
||||
result.g = Cs.g
|
||||
result.b = Cs.b
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendDarken(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendDarken(Cb.r, Cs.r)
|
||||
result.g = blendDarken(Cb.g, Cs.g)
|
||||
result.b = blendDarken(Cb.b, Cs.b)
|
||||
proc blendDarkenFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendDarkenFloat(Cb.r, Cs.r)
|
||||
result.g = blendDarkenFloat(Cb.g, Cs.g)
|
||||
result.b = blendDarkenFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendMultiply(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendMultiply(Cb.r, Cs.r)
|
||||
result.g = blendMultiply(Cb.g, Cs.g)
|
||||
result.b = blendMultiply(Cb.b, Cs.b)
|
||||
proc blendMultiplyFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendMultiplyFloat(Cb.r, Cs.r)
|
||||
result.g = blendMultiplyFloat(Cb.g, Cs.g)
|
||||
result.b = blendMultiplyFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendLinearBurn(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLinearBurn(Cb.r, Cs.r)
|
||||
result.g = blendLinearBurn(Cb.g, Cs.g)
|
||||
result.b = blendLinearBurn(Cb.b, Cs.b)
|
||||
proc blendLinearBurnFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLinearBurnFloat(Cb.r, Cs.r)
|
||||
result.g = blendLinearBurnFloat(Cb.g, Cs.g)
|
||||
result.b = blendLinearBurnFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendColorBurn(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendColorBurn(Cb.r, Cs.r)
|
||||
result.g = blendColorBurn(Cb.g, Cs.g)
|
||||
result.b = blendColorBurn(Cb.b, Cs.b)
|
||||
proc blendColorBurnFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendColorBurnFloat(Cb.r, Cs.r)
|
||||
result.g = blendColorBurnFloat(Cb.g, Cs.g)
|
||||
result.b = blendColorBurnFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendLighten(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLighten(Cb.r, Cs.r)
|
||||
result.g = blendLighten(Cb.g, Cs.g)
|
||||
result.b = blendLighten(Cb.b, Cs.b)
|
||||
proc blendLightenFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLightenFloat(Cb.r, Cs.r)
|
||||
result.g = blendLightenFloat(Cb.g, Cs.g)
|
||||
result.b = blendLightenFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendScreen(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendScreen(Cb.r, Cs.r)
|
||||
result.g = blendScreen(Cb.g, Cs.g)
|
||||
result.b = blendScreen(Cb.b, Cs.b)
|
||||
proc blendScreenFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendScreenFloat(Cb.r, Cs.r)
|
||||
result.g = blendScreenFloat(Cb.g, Cs.g)
|
||||
result.b = blendScreenFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendLinearDodge(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLinearDodge(Cb.r, Cs.r)
|
||||
result.g = blendLinearDodge(Cb.g, Cs.g)
|
||||
result.b = blendLinearDodge(Cb.b, Cs.b)
|
||||
proc blendLinearDodgeFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendLinearDodgeFloat(Cb.r, Cs.r)
|
||||
result.g = blendLinearDodgeFloat(Cb.g, Cs.g)
|
||||
result.b = blendLinearDodgeFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendColorDodge(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendColorDodge(Cb.r, Cs.r)
|
||||
result.g = blendColorDodge(Cb.g, Cs.g)
|
||||
result.b = blendColorDodge(Cb.b, Cs.b)
|
||||
proc blendColorDodgeFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendColorDodgeFloat(Cb.r, Cs.r)
|
||||
result.g = blendColorDodgeFloat(Cb.g, Cs.g)
|
||||
result.b = blendColorDodgeFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendOverlay(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendOverlay(Cb.r, Cs.r)
|
||||
result.g = blendOverlay(Cb.g, Cs.g)
|
||||
result.b = blendOverlay(Cb.b, Cs.b)
|
||||
proc blendOverlayFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendOverlayFloat(Cb.r, Cs.r)
|
||||
result.g = blendOverlayFloat(Cb.g, Cs.g)
|
||||
result.b = blendOverlayFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendHardLight(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendHardLight(Cb.r, Cs.r)
|
||||
result.g = blendHardLight(Cb.g, Cs.g)
|
||||
result.b = blendHardLight(Cb.b, Cs.b)
|
||||
proc blendHardLightFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendHardLightFloat(Cb.r, Cs.r)
|
||||
result.g = blendHardLightFloat(Cb.g, Cs.g)
|
||||
result.b = blendHardLightFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendSoftLight(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendSoftLight(Cb.r, Cs.r)
|
||||
result.g = blendSoftLight(Cb.g, Cs.g)
|
||||
result.b = blendSoftLight(Cb.b, Cs.b)
|
||||
proc blendSoftLightFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendSoftLightFloat(Cb.r, Cs.r)
|
||||
result.g = blendSoftLightFloat(Cb.g, Cs.g)
|
||||
result.b = blendSoftLightFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendDifference(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendDifference(Cb.r, Cs.r)
|
||||
result.g = blendDifference(Cb.g, Cs.g)
|
||||
result.b = blendDifference(Cb.b, Cs.b)
|
||||
proc blendDifferenceFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendDifferenceFloat(Cb.r, Cs.r)
|
||||
result.g = blendDifferenceFloat(Cb.g, Cs.g)
|
||||
result.b = blendDifferenceFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendExclusion(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendExclusion(Cb.r, Cs.r)
|
||||
result.g = blendExclusion(Cb.g, Cs.g)
|
||||
result.b = blendExclusion(Cb.b, Cs.b)
|
||||
proc blendExclusionFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
result.r = blendExclusionFloat(Cb.r, Cs.r)
|
||||
result.g = blendExclusionFloat(Cb.g, Cs.g)
|
||||
result.b = blendExclusionFloat(Cb.b, Cs.b)
|
||||
result = alphaFix(Cb, Cs, result)
|
||||
|
||||
proc blendColor(Cb, Cs: Color): Color {.inline.} =
|
||||
proc blendColorFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
let mixed = SetLum(Cs, Lum(Cb))
|
||||
alphaFix(Cb, Cs, mixed)
|
||||
|
||||
proc blendLuminosity(Cb, Cs: Color): Color {.inline.} =
|
||||
proc blendLuminosityFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
let mixed = SetLum(Cb, Lum(Cs))
|
||||
alphaFix(Cb, Cs, mixed)
|
||||
|
||||
proc blendHue(Cb, Cs: Color): Color {.inline.} =
|
||||
proc blendHueFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
let mixed = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
|
||||
alphaFix(Cb, Cs, mixed)
|
||||
|
||||
proc blendSaturation(Cb, Cs: Color): Color {.inline.} =
|
||||
proc blendSaturationFloats(Cb, Cs: Color): Color {.inline.} =
|
||||
let mixed = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
|
||||
alphaFix(Cb, Cs, mixed)
|
||||
|
||||
proc blendMask(target, blend: Color): Color {.inline.} =
|
||||
proc blendMaskFloats(target, blend: Color): Color {.inline.} =
|
||||
result.r = target.r
|
||||
result.g = target.g
|
||||
result.b = target.b
|
||||
result.a = min(target.a, blend.a)
|
||||
|
||||
proc blendSubtractMask(target, blend: Color): Color {.inline.} =
|
||||
proc blendSubtractMaskFloats(target, blend: Color): Color {.inline.} =
|
||||
result.r = target.r
|
||||
result.g = target.g
|
||||
result.b = target.b
|
||||
result.a = target.a * (1 - blend.a)
|
||||
|
||||
proc blendIntersectMask(target, blend: Color): Color {.inline.} =
|
||||
proc blendIntersectMaskFloats(target, blend: Color): Color {.inline.} =
|
||||
result.r = target.r
|
||||
result.g = target.g
|
||||
result.b = target.b
|
||||
result.a = target.a * blend.a
|
||||
|
||||
proc blendExcludeMask(target, blend: Color): Color {.inline.} =
|
||||
proc blendExcludeMaskFloats(target, blend: Color): Color {.inline.} =
|
||||
result.r = target.r
|
||||
result.g = target.g
|
||||
result.b = target.b
|
||||
result.a = abs(target.a - blend.a)
|
||||
|
||||
proc blendOverwrite(target, blend: Color): Color {.inline.} =
|
||||
proc blendOverwriteFloats(target, blend: Color): Color {.inline.} =
|
||||
result = blend
|
||||
|
||||
# proc mix*(blendMode: BlendMode, dest, src: Color): Color {.inline.} =
|
||||
# case blendMode
|
||||
# of bmNormal: blendNormal(dest, src)
|
||||
# of bmDarken: blendDarken(dest, src)
|
||||
# of bmMultiply: blendMultiply(dest, src)
|
||||
# of bmLinearBurn: blendLinearBurn(dest, src)
|
||||
# of bmColorBurn: blendColorBurn(dest, src)
|
||||
# of bmLighten: blendLighten(dest, src)
|
||||
# of bmScreen: blendScreen(dest, src)
|
||||
# of bmLinearDodge: blendLinearDodge(dest, src)
|
||||
# of bmColorDodge: blendColorDodge(dest, src)
|
||||
# of bmOverlay: blendOverlay(dest, src)
|
||||
# of bmSoftLight: blendSoftLight(dest, src)
|
||||
# of bmHardLight: blendHardLight(dest, src)
|
||||
# of bmDifference: blendDifference(dest, src)
|
||||
# of bmExclusion: blendExclusion(dest, src)
|
||||
# of bmHue: blendHue(dest, src)
|
||||
# of bmSaturation: blendSaturation(dest, src)
|
||||
# of bmColor: blendColor(dest, src)
|
||||
# of bmLuminosity: blendLuminosity(dest, src)
|
||||
# of bmMask: blendMask(dest, src)
|
||||
# of bmOverwrite: blendOverwrite(dest, src)
|
||||
# of bmSubtractMask: blendSubtractMask(dest, src)
|
||||
# of bmIntersectMask: blendIntersectMask(dest, src)
|
||||
# of bmExcludeMask: blendExcludeMask(dest, src)
|
||||
|
||||
proc alphaFix(Cb, Cs, mixed: ColorRGBA): ColorRGBA {.inline.} =
|
||||
let ab = Cb.a.int32
|
||||
let As = Cs.a.int32
|
||||
|
@ -335,63 +312,62 @@ proc alphaFix(Cb, Cs, mixed: ColorRGBA): ColorRGBA {.inline.} =
|
|||
result.b = (b div a div 255).uint8
|
||||
result.a = a.uint8
|
||||
|
||||
proc blendNormal*(a, b: ColorRGBA): ColorRGBA =
|
||||
# blendNormal(a.color, b.color).rgba
|
||||
proc blendNormal(a, b: ColorRGBA): ColorRGBA =
|
||||
result.r = b.r
|
||||
result.g = b.g
|
||||
result.b = b.b
|
||||
result = alphaFix(a, b, result)
|
||||
|
||||
proc blendDarken(a, b: ColorRGBA): ColorRGBA =
|
||||
blendDarken(a.color, b.color).rgba
|
||||
blendDarkenFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendMultiply(a, b: ColorRGBA): ColorRGBA =
|
||||
blendMultiply(a.color, b.color).rgba
|
||||
blendMultiplyFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendLinearBurn(a, b: ColorRGBA): ColorRGBA =
|
||||
blendLinearBurn(a.color, b.color).rgba
|
||||
blendLinearBurnFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendColorBurn(a, b: ColorRGBA): ColorRGBA =
|
||||
blendColorBurn(a.color, b.color).rgba
|
||||
blendColorBurnFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendLighten(a, b: ColorRGBA): ColorRGBA =
|
||||
blendLighten(a.color, b.color).rgba
|
||||
blendLightenFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendScreen(a, b: ColorRGBA): ColorRGBA =
|
||||
blendScreen(a.color, b.color).rgba
|
||||
blendScreenFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendLinearDodge(a, b: ColorRGBA): ColorRGBA =
|
||||
blendLinearDodge(a.color, b.color).rgba
|
||||
blendLinearDodgeFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendColorDodge(a, b: ColorRGBA): ColorRGBA =
|
||||
blendColorDodge(a.color, b.color).rgba
|
||||
blendColorDodgeFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendOverlay(a, b: ColorRGBA): ColorRGBA =
|
||||
blendOverlay(a.color, b.color).rgba
|
||||
blendOverlayFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendHardLight(a, b: ColorRGBA): ColorRGBA =
|
||||
blendHardLight(a.color, b.color).rgba
|
||||
blendHardLightFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendSoftLight(a, b: ColorRGBA): ColorRGBA =
|
||||
blendSoftLight(a.color, b.color).rgba
|
||||
blendSoftLightFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendDifference(a, b: ColorRGBA): ColorRGBA =
|
||||
blendDifference(a.color, b.color).rgba
|
||||
blendDifferenceFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendExclusion(a, b: ColorRGBA): ColorRGBA =
|
||||
blendExclusion(a.color, b.color).rgba
|
||||
blendExclusionFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendColor(a, b: ColorRGBA): ColorRGBA =
|
||||
blendColor(a.color, b.color).rgba
|
||||
blendColorFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendLuminosity(a, b: ColorRGBA): ColorRGBA =
|
||||
blendLuminosity(a.color, b.color).rgba
|
||||
blendLuminosityFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendHue(a, b: ColorRGBA): ColorRGBA =
|
||||
blendHue(a.color, b.color).rgba
|
||||
blendHueFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendSaturation(a, b: ColorRGBA): ColorRGBA =
|
||||
blendSaturation(a.color, b.color).rgba
|
||||
blendSaturationFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendMask(a, b: ColorRGBA): ColorRGBA =
|
||||
result.r = a.r
|
||||
|
@ -400,66 +376,39 @@ proc blendMask(a, b: ColorRGBA): ColorRGBA =
|
|||
result.a = min(a.a, b.a)
|
||||
|
||||
proc blendSubtractMask(a, b: ColorRGBA): ColorRGBA =
|
||||
blendSubtractMask(a.color, b.color).rgba
|
||||
blendSubtractMaskFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendIntersectMask(a, b: ColorRGBA): ColorRGBA =
|
||||
blendIntersectMask(a.color, b.color).rgba
|
||||
blendIntersectMaskFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendExcludeMask(a, b: ColorRGBA): ColorRGBA =
|
||||
blendExcludeMask(a.color, b.color).rgba
|
||||
blendExcludeMaskFloats(a.color, b.color).rgba
|
||||
|
||||
proc blendOverwrite(a, b: ColorRGBA): ColorRGBA =
|
||||
blendOverwrite(a.color, b.color).rgba
|
||||
blendOverwriteFloats(a.color, b.color).rgba
|
||||
|
||||
proc mix*(blendMode: BlendMode, dest, src: ColorRGBA): ColorRGBA {.inline.} =
|
||||
proc mixer*(blendMode: BlendMode): Mixer =
|
||||
case blendMode
|
||||
of bmNormal: blendNormal(dest, src)
|
||||
of bmDarken: blendDarken(dest, src)
|
||||
of bmMultiply: blendMultiply(dest, src)
|
||||
of bmLinearBurn: blendLinearBurn(dest, src)
|
||||
of bmColorBurn: blendColorBurn(dest, src)
|
||||
of bmLighten: blendLighten(dest, src)
|
||||
of bmScreen: blendScreen(dest, src)
|
||||
of bmLinearDodge: blendLinearDodge(dest, src)
|
||||
of bmColorDodge: blendColorDodge(dest, src)
|
||||
of bmOverlay: blendOverlay(dest, src)
|
||||
of bmSoftLight: blendSoftLight(dest, src)
|
||||
of bmHardLight: blendHardLight(dest, src)
|
||||
of bmDifference: blendDifference(dest, src)
|
||||
of bmExclusion: blendExclusion(dest, src)
|
||||
of bmHue: blendHue(dest, src)
|
||||
of bmSaturation: blendSaturation(dest, src)
|
||||
of bmColor: blendColor(dest, src)
|
||||
of bmLuminosity: blendLuminosity(dest, src)
|
||||
of bmMask: blendMask(dest, src)
|
||||
of bmOverwrite: blendOverwrite(dest, src)
|
||||
of bmSubtractMask: blendSubtractMask(dest, src)
|
||||
of bmIntersectMask: blendIntersectMask(dest, src)
|
||||
of bmExcludeMask: blendExcludeMask(dest, src)
|
||||
|
||||
proc mixStatic*(
|
||||
blendMode: static[BlendMode], dest, src: ColorRGBA
|
||||
): ColorRGBA {.inline.} =
|
||||
when blendMOde == bmNormal: blendNormal(dest, src)
|
||||
elif blendMOde == bmDarken: blendDarken(dest, src)
|
||||
elif blendMOde == bmMultiply: blendMultiply(dest, src)
|
||||
elif blendMOde == bmLinearBurn: blendLinearBurn(dest, src)
|
||||
elif blendMOde == bmColorBurn: blendColorBurn(dest, src)
|
||||
elif blendMOde == bmLighten: blendLighten(dest, src)
|
||||
elif blendMOde == bmScreen: blendScreen(dest, src)
|
||||
elif blendMOde == bmLinearDodge: blendLinearDodge(dest, src)
|
||||
elif blendMOde == bmColorDodge: blendColorDodge(dest, src)
|
||||
elif blendMOde == bmOverlay: blendOverlay(dest, src)
|
||||
elif blendMOde == bmSoftLight: blendSoftLight(dest, src)
|
||||
elif blendMOde == bmHardLight: blendHardLight(dest, src)
|
||||
elif blendMOde == bmDifference: blendDifference(dest, src)
|
||||
elif blendMOde == bmExclusion: blendExclusion(dest, src)
|
||||
elif blendMOde == bmHue: blendHue(dest, src)
|
||||
elif blendMOde == bmSaturation: blendSaturation(dest, src)
|
||||
elif blendMOde == bmColor: blendColor(dest, src)
|
||||
elif blendMOde == bmLuminosity: blendLuminosity(dest, src)
|
||||
elif blendMOde == bmMask: blendMask(dest, src)
|
||||
elif blendMOde == bmOverwrite: blendOverwrite(dest, src)
|
||||
elif blendMOde == bmSubtractMask: blendSubtractMask(dest, src)
|
||||
elif blendMOde == bmIntersectMask: blendIntersectMask(dest, src)
|
||||
elif blendMOde == bmExcludeMask: blendExcludeMask(dest, src)
|
||||
of bmNormal: blendNormal
|
||||
of bmDarken: blendDarken
|
||||
of bmMultiply: blendMultiply
|
||||
of bmLinearBurn: blendLinearBurn
|
||||
of bmColorBurn: blendColorBurn
|
||||
of bmLighten: blendLighten
|
||||
of bmScreen: blendScreen
|
||||
of bmLinearDodge: blendLinearDodge
|
||||
of bmColorDodge: blendColorDodge
|
||||
of bmOverlay: blendOverlay
|
||||
of bmSoftLight: blendSoftLight
|
||||
of bmHardLight: blendHardLight
|
||||
of bmDifference: blendDifference
|
||||
of bmExclusion: blendExclusion
|
||||
of bmHue: blendHue
|
||||
of bmSaturation: blendSaturation
|
||||
of bmColor: blendColor
|
||||
of bmLuminosity: blendLuminosity
|
||||
of bmMask: blendMask
|
||||
of bmOverwrite: blendOverwrite
|
||||
of bmSubtractMask: blendSubtractMask
|
||||
of bmIntersectMask: blendIntersectMask
|
||||
of bmExcludeMask: blendExcludeMask
|
||||
|
|
|
@ -409,13 +409,14 @@ proc drawCorrect*(a, b: Image, mat: Mat3, blendMode: BlendMode) =
|
|||
minFilterBy2 /= 2
|
||||
matInv = matInv * scale(vec2(0.5, 0.5))
|
||||
|
||||
let mixer = blendMode.mixer()
|
||||
for y in 0 ..< a.height:
|
||||
for x in 0 ..< a.width:
|
||||
let srcPos = matInv * vec2(x.float32 + h, y.float32 + h)
|
||||
var rgba = a.getRgbaUnsafe(x, y)
|
||||
let rgba2 = b.getRgbaSmooth(srcPos.x - h, srcPos.y - h)
|
||||
rgba = blendMode.mix(rgba, rgba2)
|
||||
a.setRgbaUnsafe(x, y, rgba)
|
||||
let
|
||||
srcPos = matInv * vec2(x.float32 + h, y.float32 + h)
|
||||
rgba = a.getRgbaUnsafe(x, y)
|
||||
rgba2 = b.getRgbaSmooth(srcPos.x - h, srcPos.y - h)
|
||||
a.setRgbaUnsafe(x, y, mixer(rgba, rgba2))
|
||||
|
||||
const h = 0.5.float32
|
||||
|
||||
|
@ -423,9 +424,10 @@ proc drawUber(
|
|||
a, b: Image,
|
||||
p, dx, dy: Vec2,
|
||||
lines: array[0..3, Segment],
|
||||
blendMode: static[BlendMode],
|
||||
smooth: static[bool]
|
||||
blendMode: BlendMode,
|
||||
smooth: bool
|
||||
) =
|
||||
let mixer = blendMode.mixer()
|
||||
for y in 0 ..< a.height:
|
||||
var
|
||||
xMin = 0
|
||||
|
@ -450,7 +452,7 @@ proc drawUber(
|
|||
xMin = xMin.clamp(0, a.width)
|
||||
xMax = xMax.clamp(0, a.width)
|
||||
|
||||
when blendMode == bmIntersectMask:
|
||||
if blendMode == bmIntersectMask:
|
||||
if xMin > 0:
|
||||
zeroMem(a.getAddr(0, y), 4 * xMin)
|
||||
|
||||
|
@ -459,17 +461,15 @@ proc drawUber(
|
|||
srcPos = p + dx * float32(x) + dy * float32(y)
|
||||
xFloat = srcPos.x - h
|
||||
yFloat = srcPos.y - h
|
||||
var
|
||||
rgba = a.getRgbaUnsafe(x, y)
|
||||
rgba2 =
|
||||
when smooth:
|
||||
if smooth:
|
||||
b.getRgbaSmooth(xFloat, yFloat)
|
||||
else:
|
||||
b.getRgbaUnsafe(xFloat.round.int, yFloat.round.int)
|
||||
rgba = blendMode.mixStatic(rgba, rgba2)
|
||||
a.setRgbaUnsafe(x, y, rgba)
|
||||
a.setRgbaUnsafe(x, y, mixer(rgba, rgba2))
|
||||
|
||||
when blendMode == bmIntersectMask:
|
||||
if blendMode == bmIntersectMask:
|
||||
if a.width - xMax > 0:
|
||||
zeroMem(a.getAddr(xMax, y), 4 * (a.width - xMax))
|
||||
|
||||
|
@ -510,56 +510,7 @@ proc draw*(a, b: Image, mat: Mat3, blendMode: BlendMode) =
|
|||
let smooth = not(dx.length == 1.0 and dy.length == 1.0 and
|
||||
mat[2, 0].fractional == 0.0 and mat[2, 1].fractional == 0.0)
|
||||
|
||||
if not smooth:
|
||||
case blendMode
|
||||
of bmNormal: a.drawUber(b, p, dx, dy, lines, bmNormal, false)
|
||||
of bmDarken: a.drawUber(b, p, dx, dy, lines, bmDarken, false)
|
||||
of bmMultiply: a.drawUber(b, p, dx, dy, lines, bmMultiply, false)
|
||||
of bmLinearBurn: a.drawUber(b, p, dx, dy, lines, bmLinearBurn, false)
|
||||
of bmColorBurn: a.drawUber(b, p, dx, dy, lines, bmColorBurn, false)
|
||||
of bmLighten: a.drawUber(b, p, dx, dy, lines, bmLighten, false)
|
||||
of bmScreen: a.drawUber(b, p, dx, dy, lines, bmScreen, false)
|
||||
of bmLinearDodge: a.drawUber(b, p, dx, dy, lines, bmLinearDodge, false)
|
||||
of bmColorDodge: a.drawUber(b, p, dx, dy, lines, bmColorDodge, false)
|
||||
of bmOverlay: a.drawUber(b, p, dx, dy, lines, bmOverlay, false)
|
||||
of bmSoftLight: a.drawUber(b, p, dx, dy, lines, bmSoftLight, false)
|
||||
of bmHardLight: a.drawUber(b, p, dx, dy, lines, bmHardLight, false)
|
||||
of bmDifference: a.drawUber(b, p, dx, dy, lines, bmDifference, false)
|
||||
of bmExclusion: a.drawUber(b, p, dx, dy, lines, bmExclusion, false)
|
||||
of bmHue: a.drawUber(b, p, dx, dy, lines, bmHue, false)
|
||||
of bmSaturation: a.drawUber(b, p, dx, dy, lines, bmSaturation, false)
|
||||
of bmColor: a.drawUber(b, p, dx, dy, lines, bmColor, false)
|
||||
of bmLuminosity: a.drawUber(b, p, dx, dy, lines, bmLuminosity, false)
|
||||
of bmMask: a.drawUber(b, p, dx, dy, lines, bmMask, false)
|
||||
of bmOverwrite: a.drawUber(b, p, dx, dy, lines, bmOverwrite, false)
|
||||
of bmSubtractMask: a.drawUber(b, p, dx, dy, lines, bmSubtractMask, false)
|
||||
of bmIntersectMask: a.drawUber(b, p, dx, dy, lines, bmIntersectMask, false)
|
||||
of bmExcludeMask: a.drawUber(b, p, dx, dy, lines, bmExcludeMask, false)
|
||||
else:
|
||||
case blendMode
|
||||
of bmNormal: a.drawUber(b, p, dx, dy, lines, bmNormal, true)
|
||||
of bmDarken: a.drawUber(b, p, dx, dy, lines, bmDarken, true)
|
||||
of bmMultiply: a.drawUber(b, p, dx, dy, lines, bmMultiply, true)
|
||||
of bmLinearBurn: a.drawUber(b, p, dx, dy, lines, bmLinearBurn, true)
|
||||
of bmColorBurn: a.drawUber(b, p, dx, dy, lines, bmColorBurn, true)
|
||||
of bmLighten: a.drawUber(b, p, dx, dy, lines, bmLighten, true)
|
||||
of bmScreen: a.drawUber(b, p, dx, dy, lines, bmScreen, true)
|
||||
of bmLinearDodge: a.drawUber(b, p, dx, dy, lines, bmLinearDodge, true)
|
||||
of bmColorDodge: a.drawUber(b, p, dx, dy, lines, bmColorDodge, true)
|
||||
of bmOverlay: a.drawUber(b, p, dx, dy, lines, bmOverlay, true)
|
||||
of bmSoftLight: a.drawUber(b, p, dx, dy, lines, bmSoftLight, true)
|
||||
of bmHardLight: a.drawUber(b, p, dx, dy, lines, bmHardLight, true)
|
||||
of bmDifference: a.drawUber(b, p, dx, dy, lines, bmDifference, true)
|
||||
of bmExclusion: a.drawUber(b, p, dx, dy, lines, bmExclusion, true)
|
||||
of bmHue: a.drawUber(b, p, dx, dy, lines, bmHue, true)
|
||||
of bmSaturation: a.drawUber(b, p, dx, dy, lines, bmSaturation, true)
|
||||
of bmColor: a.drawUber(b, p, dx, dy, lines, bmColor, true)
|
||||
of bmLuminosity: a.drawUber(b, p, dx, dy, lines, bmLuminosity, true)
|
||||
of bmMask: a.drawUber(b, p, dx, dy, lines, bmMask, true)
|
||||
of bmOverwrite: a.drawUber(b, p, dx, dy, lines, bmOverwrite, true)
|
||||
of bmSubtractMask: a.drawUber(b, p, dx, dy, lines, bmSubtractMask, true)
|
||||
of bmIntersectMask: a.drawUber(b, p, dx, dy, lines, bmIntersectMask, true)
|
||||
of bmExcludeMask: a.drawUber(b, p, dx, dy, lines, bmExcludeMask, true)
|
||||
a.drawUber(b, p, dx, dy, lines, blendMode, smooth)
|
||||
|
||||
proc draw*(a, b: Image, pos = vec2(0, 0), blendMode = bmNormal) {.inline.} =
|
||||
a.draw(b, translate(pos), blendMode)
|
||||
|
|
|
@ -4,7 +4,7 @@ block:
|
|||
var c: Image
|
||||
var a = newImage(1000, 1000)
|
||||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(1000, 1000)
|
||||
var b = newImage(500, 500)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
|
||||
timeIt "drawCorrect bmNormal":
|
||||
|
@ -14,7 +14,7 @@ block:
|
|||
block:
|
||||
var a = newImage(1000, 1000)
|
||||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(1000, 1000)
|
||||
var b = newImage(500, 500)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
|
||||
timeIt "draw bmNormal":
|
||||
|
@ -24,7 +24,7 @@ block:
|
|||
block:
|
||||
var a = newImage(1000, 1000)
|
||||
a.fill(rgba(255, 0, 0, 255))
|
||||
var b = newImage(1000, 1000)
|
||||
var b = newImage(500, 500)
|
||||
b.fill(rgba(0, 255, 0, 255))
|
||||
|
||||
timeIt "draw Smooth bmNormal":
|
||||
|
|
Loading…
Reference in a new issue