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