Arx1meD
1st July 2021, 13:55
Overlay_MTools
Overlay puts two clips on top of each other with an optional masking, and using different blending methods. Furthermore opacity can be adjusted for the overlay clip.
This script is not as versatile as the Overlay filter in AviSynth (http://avisynth.nl/index.php/Overlay). But it has more blend modes and is a bit faster. Input clips (base, overlay and mask) must be in the same colorspace and have the same frame size.
Attention!
1. Overlay in AviSynth, this script and Photoshop overlay methods give different results. If you want to get a result similar to the one in Photoshop, then set blend_rgb=true in function.
2. In AviSynth Overlay, softlight and hardlight modes give completely different results. Because the source code (https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/overlay/OF_softhardlight.cpp) contains other formulas for these modes. In my opinion, this is a mistake (based on information found about blending modes). The softlight mode in AviSynth Overlay is actually grainmerge, and hardlight is actually linearlight.
# Overlay_MTools() v1.1
#
# v1.0 : - first release
# v1.1 : - changed the blending method when is no mask clip
/*
Needed plugins: MaskTools2 v2.2.16 or greater.
https://github.com/pinterf/masktools/releases
http://avisynth.nl/index.php/Masktools2
Overlay_MTools(source, over, mask, mode, opacity, chroma, blend_rgb)
source:
-------
This clip is base.
over:
-----
This clip will be placed on top of the base clip.
mask:
-----
This clip will be used as the transparency mask for the overlay clip.
The darker the image is, the more transparent will the overlay clip be.
Default: Undefined
mode:
-----
Mode (or overlay method) defines how overlay clip should be overlaid on base image.
Group | Mode
-----------|-----------------------------------------------------------------------------------------------------------------
Simple | blend, average
Darken | darken, multiply, colorburn, linearburn
Lighten | lighten, screen, colordodge, add (aka lineardodge)
Mix | overlay, softlight, hardlight, vividlight, linearlight, pinlight, hardmix, softburn, softdodge, interpolation
Difference | difference, difference_grey, subtract, exclusion, negation, extremity, divide, phoenix, grainextract, grainmerge
Quadratic | reflect, glow, freeze, heat
Binary | AND, OR, XOR - These modes available for 8-bit color bit depth only
Default: "blend"
opacity:
--------
This will set how transparent overlay clip will be. The value 0 is transparent and 1.0 is fully opague.
Range: 0 ... 1.0
Default: 1.0
chroma:
-------
This option specifies whether to use chroma channels.
true - it means "process" (set u = v = 3 in mt_lut() MaskTools2).
false - it means "copy" or "copy first" (set u = v = 2).
Default: false
blend_rgb:
----------
Use this option if you want to get a blending effect like in Photoshop (with RGB color space).
true - do blending in RGB color space.
false - do blending in YUV (YCbCr) color space.
Default: false
Usage Default:
Overlay_MTools(source, over, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
or with clip mask
Overlay_MTools(source, over, mask=mask, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
*/
function Overlay_MTools(clip source, clip over, clip "mask", string "mode", float "opacity", bool "chroma", bool "blend_rgb"){
mask = Default(mask, Undefined)
mode = Default(mode, "blend")
opacity = Default(opacity, 1.0)
chroma = Default(chroma, false)
blend_rgb = Default(blend_rgb, false)
src_411 = source.IsYV411
src_420 = source.Is420
src_422 = source.Is422
src_444 = source.Is444
src_Y = source.IsY
src_Pl = source.IsPlanarRGB
# Simple modes:
md = mode=="blend" ? "x 0 * y +" : "ERR"
md = mode=="average" ? "x y + 2 /" : md
# Darken/Burn modes:
md = mode=="darken" ? "x y min" : md
md = mode=="multiply" ? "x y * 255 /" : md
md = mode=="colorburn" ? "y 0 == y 255 255 x - 255 * y / - ?" : md
md = mode=="linearburn" ? "x y + 255 < 0 x y + 255 - ?" : md
# Lighten/Dodge modes:
md = mode=="lighten" ? "x y max" : md
md = mode=="screen" ? "x y + x y * 255 / -" : md
md = mode=="colordodge" ? "y 255 == y x 255 * 255 y - / ?" : md # inverse the ColorBurn
md = mode=="add" ? "x y +" : md # aka LinearDodge mode
# Mix/Combine modes:
md = mode=="overlay" ? "x 127.5 > 2 x y + x y * 255 / - * 255 - x y * 127.5 / ?" : md # inverse the HardLight (like in Photoshop)
md = mode=="softlight" ? "x 255 / x y 2 * + x y * 127.5 / - *" : md # combination of Multiply and Screen (like in Photoshop)
md = mode=="hardlight" ? "y 127.5 > 2 x y + x y * 255 / - * 255 - x y * 127.5 / ?" : md # combination of Multiply and Screen (like in Photoshop)
md = mode=="vividlight" ? "y 127.5 < y 0 <= 2 y * 255 255 x - 255 * 2 y * / - ? 2 y 127.5 - * 255 >= 2 y 127.5 - * x 255 * 255 2 y 127.5 - * - / ? ?" : md # combination of ColorBurn and ColorDodge
md = mode=="linearlight" ? "x 2 y * + 255 -" : md # combination of LinearBurn and LinearDodge (or stamp mode)
md = mode=="pinlight" ? "y 127.5 < x 2 y * min x 2 y 127.5 - * max ?" : md # combination of Darken and Lighten
md = mode=="hardmix" ? "x 255 y - < 0 255 ?" : md # or (vividlight < 128 ? 0 : 255)
md = mode=="softburn" ? "x y + 255 < x 255 == x 255 y * 2 255 x - * / ? y 0 == y 255 255 x - 255 * y 2 * / - ? ?" : md # combination of ColorBurn and inverse ColorDodge
md = mode=="softdodge" ? "x y + 255 < y 255 == y x 255 * 2 255 y - * / ? x 0 == x 255 255 255 y - * 2 x * / - ? ?" : md # combination of ColorDodge and inverse ColorBurn
md = mode=="interpolation" ? "255 0.5 pi x * 255 / cos 4 / - pi y * 255 / cos 4 / - *" : md
# Difference modes:
md = mode=="difference" ? "x y - abs" : md
md = mode=="difference_grey" ? "x y - abs 127.5 +" : md # like in AviSynth, use with chroma=true
md = mode=="subtract" ? "x y -" : md
md = mode=="exclusion" ? "x y + x y * 127.5 / -" : md
md = mode=="negation" ? "255 255 x - y - abs -" : md
md = mode=="extremity" ? "255 x - y - abs" : md # inverse the Difference
md = mode=="divide" ? "y 0 <= 255 255 x * y / ?" : md
md = mode=="phoenix" ? "x y min x y max - 255 +" : md # inverse the Negation
md = mode=="grainextract" ? "x y - 127.5 +" : md
md = mode=="grainmerge" ? "x y + 127.5 -" : md # inverse the GrainExtract
# Quadratic modes:
md = mode=="reflect" ? "y 255 == y x x * 255 y - / ?" : md
md = mode=="glow" ? "x 255 == x y y * 255 x - / ?" : md # inverse the Reflect
md = mode=="freeze" ? "y 0 == 0 255 255 x - 2 ^ y / -?" : md
md = mode=="heat" ? "x 0 == 0 255 255 y - 2 ^ x / -?" : md # inverse the Freeze
# Binary modes:
md = mode=="AND" ? "x y &u" : md
md = mode=="OR" ? "x y |u" : md
md = mode=="XOR" ? "x y @u" : md
Assert(opacity >= 0 && opacity <= 1, "Overlay_MTools: Opacity must be in the range 0 to 1.0")
Assert(md != "ERR", "Overlay_MTools: Invalid 'mode' specified")
bpc = source.BitsPerComponent
chrom = blend_rgb || chroma ? "process" : "copy"
# chrom_m = blend_rgb && src_Pl ? "process" : !src_Pl ? "copy" : chrom
# mask = Defined(mask) ? mask : source.mt_lut("range_max", Y=3, chroma=chrom_m)
source = blend_rgb ? src_Pl || src_Y ? source : source.ConvertToPlanarRGB() : source
over = blend_rgb ? src_Pl || src_Y ? over : over.ConvertToPlanarRGB() : over
mask = Defined(mask) ? blend_rgb ? src_Pl || src_Y ? mask : mask.ConvertToPlanarRGB() : mask : Undefined
# mask = blend_rgb ? src_Pl || src_Y ? mask : mask.ConvertToPlanarRGB() : mask
# with a mask slower
# blend = mt_lutxyz(source, over, mask,
# \ expr="x x "+md+" - z 255 / * "+String(opacity)+" * -",
# \ Y=3, chroma=chrom, scale_inputs=bpc==8?"none":"allf", use_expr=bpc==8?0:2)
blend = mt_lutxy(source, over,
\ expr="x x "+md+" - "+String(opacity)+" * -",
\ Y=3, chroma=chrom, scale_inputs=bpc==8?"none":"allf", use_expr=bpc==8?0:2)
blend = Defined(mask) ? mt_merge(source, blend, mask, Y=3, chroma=chrom) : blend
out = src_411 ? blend.ConvertToYUV411()
\ : src_420 ? blend.ConvertToYUV420()
\ : src_422 ? blend.ConvertToYUV422()
\ : src_444 ? blend.ConvertToYUV444()
\ : src_Y ? blend.ConvertToY()
\ : blend
return blend_rgb ? out : blend
}
Usage Default:
Overlay_MTools(source, over, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
or with clip mask
Overlay_MTools(source, over, mask=mask, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
Examples of what the script does. Only math
Source clip (aka base clip) - color changes in the X-axis
https://images2.imgbox.com/a0/20/UFoqoAVB_o.png
Overlay clip - color changes in the Y-axis
https://images2.imgbox.com/cd/3b/MNbLvyWb_o.png
Result
https://images2.imgbox.com/ad/da/uYP4joD3_o.png
Other Overlay scripts: UU_mt_blend (http://avisynth.nl/index.php/UU_mt_blend), Blend_MT_alpha3 (https://forum.doom9.org/showthread.php?p=1400434#post1400434), ex_blend (https://github.com/Dogway/Avisynth-Scripts/blob/9d2f113742a5a7fea3cb4945f78768132e1f69b3/ExTools.avsi), OverlayPlus (http://avisynth.nl/index.php/OverlayPlus) (in forum (https://forum.doom9.org/showthread.php?t=183185))
More information about Blend Modes:
https://en.wikipedia.org/wiki/Blend_modes
https://stackoverflow.com/questions/5919663/how-does-photoshop-blend-two-images-together
https://www.w3.org/TR/compositing/#blending
https://web.archive.org/web/20120728013719/http://jswidget.com/blog/2011/03/11/image-blending-algorithmpart-i
https://help.maxon.net/us/index.html#11718
https://ww2.mathworks.cn/matlabcentral/fileexchange/52513-image-blending-functions
Overlay puts two clips on top of each other with an optional masking, and using different blending methods. Furthermore opacity can be adjusted for the overlay clip.
This script is not as versatile as the Overlay filter in AviSynth (http://avisynth.nl/index.php/Overlay). But it has more blend modes and is a bit faster. Input clips (base, overlay and mask) must be in the same colorspace and have the same frame size.
Attention!
1. Overlay in AviSynth, this script and Photoshop overlay methods give different results. If you want to get a result similar to the one in Photoshop, then set blend_rgb=true in function.
2. In AviSynth Overlay, softlight and hardlight modes give completely different results. Because the source code (https://github.com/AviSynth/AviSynthPlus/blob/master/avs_core/filters/overlay/OF_softhardlight.cpp) contains other formulas for these modes. In my opinion, this is a mistake (based on information found about blending modes). The softlight mode in AviSynth Overlay is actually grainmerge, and hardlight is actually linearlight.
# Overlay_MTools() v1.1
#
# v1.0 : - first release
# v1.1 : - changed the blending method when is no mask clip
/*
Needed plugins: MaskTools2 v2.2.16 or greater.
https://github.com/pinterf/masktools/releases
http://avisynth.nl/index.php/Masktools2
Overlay_MTools(source, over, mask, mode, opacity, chroma, blend_rgb)
source:
-------
This clip is base.
over:
-----
This clip will be placed on top of the base clip.
mask:
-----
This clip will be used as the transparency mask for the overlay clip.
The darker the image is, the more transparent will the overlay clip be.
Default: Undefined
mode:
-----
Mode (or overlay method) defines how overlay clip should be overlaid on base image.
Group | Mode
-----------|-----------------------------------------------------------------------------------------------------------------
Simple | blend, average
Darken | darken, multiply, colorburn, linearburn
Lighten | lighten, screen, colordodge, add (aka lineardodge)
Mix | overlay, softlight, hardlight, vividlight, linearlight, pinlight, hardmix, softburn, softdodge, interpolation
Difference | difference, difference_grey, subtract, exclusion, negation, extremity, divide, phoenix, grainextract, grainmerge
Quadratic | reflect, glow, freeze, heat
Binary | AND, OR, XOR - These modes available for 8-bit color bit depth only
Default: "blend"
opacity:
--------
This will set how transparent overlay clip will be. The value 0 is transparent and 1.0 is fully opague.
Range: 0 ... 1.0
Default: 1.0
chroma:
-------
This option specifies whether to use chroma channels.
true - it means "process" (set u = v = 3 in mt_lut() MaskTools2).
false - it means "copy" or "copy first" (set u = v = 2).
Default: false
blend_rgb:
----------
Use this option if you want to get a blending effect like in Photoshop (with RGB color space).
true - do blending in RGB color space.
false - do blending in YUV (YCbCr) color space.
Default: false
Usage Default:
Overlay_MTools(source, over, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
or with clip mask
Overlay_MTools(source, over, mask=mask, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
*/
function Overlay_MTools(clip source, clip over, clip "mask", string "mode", float "opacity", bool "chroma", bool "blend_rgb"){
mask = Default(mask, Undefined)
mode = Default(mode, "blend")
opacity = Default(opacity, 1.0)
chroma = Default(chroma, false)
blend_rgb = Default(blend_rgb, false)
src_411 = source.IsYV411
src_420 = source.Is420
src_422 = source.Is422
src_444 = source.Is444
src_Y = source.IsY
src_Pl = source.IsPlanarRGB
# Simple modes:
md = mode=="blend" ? "x 0 * y +" : "ERR"
md = mode=="average" ? "x y + 2 /" : md
# Darken/Burn modes:
md = mode=="darken" ? "x y min" : md
md = mode=="multiply" ? "x y * 255 /" : md
md = mode=="colorburn" ? "y 0 == y 255 255 x - 255 * y / - ?" : md
md = mode=="linearburn" ? "x y + 255 < 0 x y + 255 - ?" : md
# Lighten/Dodge modes:
md = mode=="lighten" ? "x y max" : md
md = mode=="screen" ? "x y + x y * 255 / -" : md
md = mode=="colordodge" ? "y 255 == y x 255 * 255 y - / ?" : md # inverse the ColorBurn
md = mode=="add" ? "x y +" : md # aka LinearDodge mode
# Mix/Combine modes:
md = mode=="overlay" ? "x 127.5 > 2 x y + x y * 255 / - * 255 - x y * 127.5 / ?" : md # inverse the HardLight (like in Photoshop)
md = mode=="softlight" ? "x 255 / x y 2 * + x y * 127.5 / - *" : md # combination of Multiply and Screen (like in Photoshop)
md = mode=="hardlight" ? "y 127.5 > 2 x y + x y * 255 / - * 255 - x y * 127.5 / ?" : md # combination of Multiply and Screen (like in Photoshop)
md = mode=="vividlight" ? "y 127.5 < y 0 <= 2 y * 255 255 x - 255 * 2 y * / - ? 2 y 127.5 - * 255 >= 2 y 127.5 - * x 255 * 255 2 y 127.5 - * - / ? ?" : md # combination of ColorBurn and ColorDodge
md = mode=="linearlight" ? "x 2 y * + 255 -" : md # combination of LinearBurn and LinearDodge (or stamp mode)
md = mode=="pinlight" ? "y 127.5 < x 2 y * min x 2 y 127.5 - * max ?" : md # combination of Darken and Lighten
md = mode=="hardmix" ? "x 255 y - < 0 255 ?" : md # or (vividlight < 128 ? 0 : 255)
md = mode=="softburn" ? "x y + 255 < x 255 == x 255 y * 2 255 x - * / ? y 0 == y 255 255 x - 255 * y 2 * / - ? ?" : md # combination of ColorBurn and inverse ColorDodge
md = mode=="softdodge" ? "x y + 255 < y 255 == y x 255 * 2 255 y - * / ? x 0 == x 255 255 255 y - * 2 x * / - ? ?" : md # combination of ColorDodge and inverse ColorBurn
md = mode=="interpolation" ? "255 0.5 pi x * 255 / cos 4 / - pi y * 255 / cos 4 / - *" : md
# Difference modes:
md = mode=="difference" ? "x y - abs" : md
md = mode=="difference_grey" ? "x y - abs 127.5 +" : md # like in AviSynth, use with chroma=true
md = mode=="subtract" ? "x y -" : md
md = mode=="exclusion" ? "x y + x y * 127.5 / -" : md
md = mode=="negation" ? "255 255 x - y - abs -" : md
md = mode=="extremity" ? "255 x - y - abs" : md # inverse the Difference
md = mode=="divide" ? "y 0 <= 255 255 x * y / ?" : md
md = mode=="phoenix" ? "x y min x y max - 255 +" : md # inverse the Negation
md = mode=="grainextract" ? "x y - 127.5 +" : md
md = mode=="grainmerge" ? "x y + 127.5 -" : md # inverse the GrainExtract
# Quadratic modes:
md = mode=="reflect" ? "y 255 == y x x * 255 y - / ?" : md
md = mode=="glow" ? "x 255 == x y y * 255 x - / ?" : md # inverse the Reflect
md = mode=="freeze" ? "y 0 == 0 255 255 x - 2 ^ y / -?" : md
md = mode=="heat" ? "x 0 == 0 255 255 y - 2 ^ x / -?" : md # inverse the Freeze
# Binary modes:
md = mode=="AND" ? "x y &u" : md
md = mode=="OR" ? "x y |u" : md
md = mode=="XOR" ? "x y @u" : md
Assert(opacity >= 0 && opacity <= 1, "Overlay_MTools: Opacity must be in the range 0 to 1.0")
Assert(md != "ERR", "Overlay_MTools: Invalid 'mode' specified")
bpc = source.BitsPerComponent
chrom = blend_rgb || chroma ? "process" : "copy"
# chrom_m = blend_rgb && src_Pl ? "process" : !src_Pl ? "copy" : chrom
# mask = Defined(mask) ? mask : source.mt_lut("range_max", Y=3, chroma=chrom_m)
source = blend_rgb ? src_Pl || src_Y ? source : source.ConvertToPlanarRGB() : source
over = blend_rgb ? src_Pl || src_Y ? over : over.ConvertToPlanarRGB() : over
mask = Defined(mask) ? blend_rgb ? src_Pl || src_Y ? mask : mask.ConvertToPlanarRGB() : mask : Undefined
# mask = blend_rgb ? src_Pl || src_Y ? mask : mask.ConvertToPlanarRGB() : mask
# with a mask slower
# blend = mt_lutxyz(source, over, mask,
# \ expr="x x "+md+" - z 255 / * "+String(opacity)+" * -",
# \ Y=3, chroma=chrom, scale_inputs=bpc==8?"none":"allf", use_expr=bpc==8?0:2)
blend = mt_lutxy(source, over,
\ expr="x x "+md+" - "+String(opacity)+" * -",
\ Y=3, chroma=chrom, scale_inputs=bpc==8?"none":"allf", use_expr=bpc==8?0:2)
blend = Defined(mask) ? mt_merge(source, blend, mask, Y=3, chroma=chrom) : blend
out = src_411 ? blend.ConvertToYUV411()
\ : src_420 ? blend.ConvertToYUV420()
\ : src_422 ? blend.ConvertToYUV422()
\ : src_444 ? blend.ConvertToYUV444()
\ : src_Y ? blend.ConvertToY()
\ : blend
return blend_rgb ? out : blend
}
Usage Default:
Overlay_MTools(source, over, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
or with clip mask
Overlay_MTools(source, over, mask=mask, mode="blend", opacity=1.0, chroma=false, blend_rgb=false)
Examples of what the script does. Only math
Source clip (aka base clip) - color changes in the X-axis
https://images2.imgbox.com/a0/20/UFoqoAVB_o.png
Overlay clip - color changes in the Y-axis
https://images2.imgbox.com/cd/3b/MNbLvyWb_o.png
Result
https://images2.imgbox.com/ad/da/uYP4joD3_o.png
Other Overlay scripts: UU_mt_blend (http://avisynth.nl/index.php/UU_mt_blend), Blend_MT_alpha3 (https://forum.doom9.org/showthread.php?p=1400434#post1400434), ex_blend (https://github.com/Dogway/Avisynth-Scripts/blob/9d2f113742a5a7fea3cb4945f78768132e1f69b3/ExTools.avsi), OverlayPlus (http://avisynth.nl/index.php/OverlayPlus) (in forum (https://forum.doom9.org/showthread.php?t=183185))
More information about Blend Modes:
https://en.wikipedia.org/wiki/Blend_modes
https://stackoverflow.com/questions/5919663/how-does-photoshop-blend-two-images-together
https://www.w3.org/TR/compositing/#blending
https://web.archive.org/web/20120728013719/http://jswidget.com/blog/2011/03/11/image-blending-algorithmpart-i
https://help.maxon.net/us/index.html#11718
https://ww2.mathworks.cn/matlabcentral/fileexchange/52513-image-blending-functions