Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
6th April 2017, 18:20 | #1 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
Request: port avisynth mftoon2 to vapoursynth
EDIT:
Download a bettter/fixed version of mfToon2 for vapoursynth here: https://gist.github.com/Frechdachs/b...10cf7239d53d0c Thanks @Frechdachs, Myrsloik & WolframRhodium --------------- Could someone be so kind and port this avisynth filter to vapoursynth? http://avisynth.nl/index.php/MfToon http://avisynth.nl/images/MfToon-v0.54.avsi The dependencies are: aWarpSharp2 MaskTools2 WarpSharp This script uses Unsharpmask() and XSharpen() from warpsharp. What would be а vapoursynth equivalent for this? You can find a Tweak() port here https://forum.doom9.org/showthread.php?t=172808 Thanks! Code:
def mftoon2(clip, twidth=None, theight=None, ssw=4, ssh=4, xstren=255, xthresh=255, cwarp=True, sharpen=True, strength=255, wdepth=16.0, wblur=1, wthresh=0.5, drange=64, dboost=1.0, dlimit=30, debug=False, doutput=None, dclip=None, show=False, scolor="$FF00FF"): return clip Code:
############################## ## ## ## mfToon v0.52 by mf ^^; ## ## ## ## I would claim copyright, ## ## but as I do not give my ## ## real identity, I can't. ## ## So as netizen to net- ## ## izen, I ask you, please ## ## don't do lame stuff ## ## with my script, like ## ## claiming you made it. ## ## Thank you. ## ## ## ############################## ############################## ## ## ################################ ################################ ## ## ## Usage: ## ## ## ## Import("mfToon-v0.52.avs") ## ## mfToon() or mfToonLite() ## ## ## ################################ ################################ #### ## ## New maskbuilding ("cartoon" edgedetection), and mfToon-lite to use in realtime in your ## ffdshow "AVISynth" section. It's not meant for encoding, only playback. ## ## function mfToon2(clip orig, int "twidth", int "theight", int "ssw", int "ssh", int "xstren", \ int "xthresh", bool "cwarp", bool "sharpen", int "strength", float "wdepth", int "wblur", \ float "wthresh", int "drange", float "dboost", int "dlimit", bool "debug", bool "doutput", \ string "dclip", bool "show", int "scolor") { # normal params strength = Default(strength, 255) # line darkening strength, 0-255 sharpen = Default(sharpen, true) # sharpening on/off cwarp = Default(cwarp, true) # chroma warp on/off cwarp2 = cwarp ? 1 : 0 wdepth = Default(wdepth, 16.0) # warping depth, ?-? wblur = Default(wblur, 1) # warping blur level, ?-? wthresh = Default(wthresh, 0.5) # warping threshold, 0.0-1.0 ssw = Default(ssw, 4) # supersample factor horizontally, 0-inf ssh = Default(ssh, 4) # supersample factor vertically, 0-inf twidth = Default(twidth, orig.width) # target width (useful for cropping), 0-inf theight = Default(theight, orig.height) # target height (useful for cropping), 0-inf show = Default(show, false) # show which lines are being darkened scolor = Default(scolor, $FF00FF) # which color to show lines in # advanced params xstren = Default(xstren, 255) # xsharpening strength, 0-255 xthresh = Default(xthresh, 255) # xsharpening threshold, 0-255 ## Where have all the params gone?! - They were useless as of 0.5, but I forgot to clean them. drange = Default(drange, 64) # detail range, 0-255 dboost = Default(dboost, 1.0) # detail boost, 0.1-10.0 dlimit = Default(dlimit, 30) # detail limiter, 0-255 debug = Default(debug, false) # debug mode on/off doutput = Default(doutput, true) # print debug info on processed image dclip = Default(dclip, "rclip1") # which stage of the processing to show ssw2 = twidth * ssw ssh2 = theight * ssh sharpen2 = show ? false : sharpen orig.Unsharpmask(300, 4, 0) sharp = last mt_merge(sharp, orig, orig) sharp1 = last mt_merge(sharp1, orig, orig) sharp2 = last greymask = orig.mt_invert(u=-128, v=-128) detailmaskpre0 = orig.mt_edge(thy1 = 3, thy2 = 255, thc1 = 255, thc2 = 255, mode = "cartoon", Y=3, V=1, U=1) \ .Tweak(0.0, 1.0, drange, 1.0).Levels(60, dboost, 255, 0, 255) \ .Levels(0, dboost, dlimit, 255, 0).mt_inflate(u=-128, v=-128).mt_deflate().mt_deflate().mt_deflate() detailmaskpre1 = orig.mt_edge(thy1 = 3, thy2 = 255, thc1 = 255, thc2 = 255, mode = "roberts", Y=3, V=1, U=1) \ .Tweak(0.0, 1.0, drange, 1.0).Levels(60, dboost, 255, 0, 255) \ .Levels(0, dboost, dlimit, 255, 0).mt_inflate(u=-128, v=-128) detailmaskpre2 = mt_lut(detailmaskpre1, "x x * x * x * 256 / 256 / 256 /").Blur(1.0).Levels(0, 1.0, 190, 0, 255) mt_deflate() detailmask = last white = orig.mt_binarize(Y=-255,U=-128,V=-128) linemask1 = mt_merge(white, detailmask, orig.mt_invert()).mt_invert() linemask = (strength == 255) ? linemask1 : linemask1.levels(0, 1.0, 255, 0, strength) color = BlankClip(orig, color=scolor) sharp3 = show ? color : sharp2 dark = mt_merge(orig, sharp3, linemask, Y=3, U=1, V=1) darkmerged = dark.MergeChroma(orig) finaldark = show ? dark : darkmerged semifinal=orig.BicubicResize(twidth, theight, 0, 0.75) final = dark.BicubicResize(ssw2, ssh2, 0, 0.75).XSharpen(xstren, xthresh) \ .BicubicResize(twidth, theight, 0, 0.75).MergeChroma(semifinal) \ .aWarpSharp(cm=cwarp2, depth=wdepth, blurlevel=wblur, thresh=wthresh) rclip1 = sharpen2 ? final : finaldark Eval("dclip1 = doutput ? "+dclip+" : orig") dstring1 = "mfToon v0.52 by mf - Debug mode ;p" dstring2 = "Pointsized: DisabledxDisabled" dstring3 = "Bicubicsized: " + String(ssw2) + "x" + String(ssh2) dstring4 = "Outputsize: " + String(twidth) + "x" + String(theight) dstring5 = "Debug image: " + dclip clipstring = sharpen2 ? "final" : "finaldark" dstring6 = "Output image: " + clipstring dclip2 = dclip1.Subtitle(dstring1).Subtitle(dstring2, y=33).Subtitle(dstring3, y=48) \ .Subtitle(dstring4, y=63).Subtitle(dstring5, y=78).Subtitle(dstring6, y=93) rclip2 = debug ? dclip2 : rclip1 return rclip2 }
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database Last edited by ChaosKing; 9th April 2017 at 23:01. |
6th April 2017, 20:32 | #2 | Link |
Professional Code Monkey
Join Date: Jun 2003
Location: Kinnarps Chair
Posts: 2,548
|
I checked the algorithm and you can implement XSharpen with minimum, maximum and expr. I'll post my version in a bit.
Unsharpmask is just a big radius blur with some thresholding as well. I think you'd need a box blur filter to make it fast but it should be possible to approximate with any other large radius blur.
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet |
7th April 2017, 22:49 | #3 | Link |
Professional Code Monkey
Join Date: Jun 2003
Location: Kinnarps Chair
Posts: 2,548
|
Code:
def Xsharpen(clip, strength = 128, threshold = 8): return vs.core.std.Expr([clip, clip.std.Maximum(planes=0), clip.std.Minimum(planes=0)], ["y x - x z - min {} < x z - y x - < z y ? {} * x {} * + x ?".format(threshold, strength / 256, (256 - strength) / 256), ""])
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet |
8th April 2017, 00:01 | #4 | Link |
Professional Code Monkey
Join Date: Jun 2003
Location: Kinnarps Chair
Posts: 2,548
|
Bonus thing. Have fun porting!
Code:
def UnsharpMask(clip, strength = 64, radius = 3, threshold = 8): blurclip = clip.std.Convolution([1] * (radius * 2 + 1), planes=0, mode="v") blurclip = blurclip.std.Convolution([1] * (radius * 2 + 1), planes=0, mode="h") return vs.core.std.Expr([clip, blurclip], ["x y - abs {} > x y - {} * x + x ?".format(threshold, strength/128), ""])
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet |
8th April 2017, 09:07 | #5 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
Nice! Thank you, this helps a lot.
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database |
8th April 2017, 14:30 | #6 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
So here is my first (alpha) port. It uses masktools2 from avisynth for now because I don't know all the vapoursynth "masktools" equivalents.
(I used an older masktools x64 build from here https://github.com/tp7/masktools/releases the Avisynth+ masktools by pinterf https://github.com/pinterf/masktools/releases is chrashing immediately: Plugin /coreplugins/AvsCompat.dll tried to register 'mt_invert' more than once. Plugin /coreplugins/AvsCompat.dll tried to register 'mt_invert' more than once. ) @Myrsloik Are Avisynth+ plugins supported by vapoursynth? This gives me different results in avs and vp: Code:
orig.Unsharpmask(300, 4, 0) sharp = last mt_merge(sharp, orig, orig) Code:
orig = UnsharpMask(clip, 300, 4, 0) sharp = clip clip = core.std.MaskedMerge(sharp, orig, orig) [OR clip = core.avs.mt_merge(sharp, orig, orig)] http://i.imgur.com/jRRPPVD.jpg I also noticed something... there is detailmaskpre0, detailmaskpre1, detailmaskpre2 in mftoon, but it is not used anywhere in the script later and slows down by a factor of 10 When I uncomment the lines -> 13fps vs 150fps, same output. That's why the dboost parameter did nothing for me xD Would this be a correct translation to vapoursynth? Code:
mt_merge(sharp, orig, orig) -> clip = core.std.MaskedMerge(sharp, orig, orig) dark.BicubicResize(ssw2, ssh2, 0, 0.75) ->dark.resize.Bicubic(ssw2, ssh2, filter_param_a = 0, filter_param_b = 0.75) darkmerged = dark.avs.MergeChroma(orig) -> darkmerged = core.std.ShufflePlanes(clips=[dark, orig], planes=[0, 1, 2], colorfamily=clip.format.color_family) This is my port so far (I tried to stay close to avisynth code, for now at least): Code:
def mftoon2(clip, twidth=None, theight=None, ssw=4, ssh=4, xstren=255, xthresh=255, cwarp=True, sharpen=True, strength=255, wdepth=16, wblur=1, wthresh=128, drange=64, dboost=1.0, dlimit=30, debug=False, doutput=None, dclip=None, show=False, scolor="$FF00FF"): #NOTE #awarpsharp1 wthresh of 0.5 == 128 in awarpsharp2 #http://avisynth.nl/index.php/AWarpsharp2/aWarpSharp cwarp2 = 0 if(cwarp): cwarp2 = 1 ssw = 4 # supersample factor horizontally, 0-inf ssh = 4 # supersample factor vertically, 0-inf twidth = clip.width theight = clip.height ssw2 = twidth * ssw ssh2 = theight * ssh orig = UnsharpMask(clip, 300, 4, 0) sharp = clip clip = core.std.MaskedMerge(sharp, orig, orig) #clip = core.avs.mt_merge(sharp, orig, orig) sharp1 = clip clip = core.std.MaskedMerge(sharp1, orig, orig) #clip = core.avs.mt_merge(sharp1, orig, orig) sharp2 = clip graymask = orig.avs.mt_invert(U=-128, Y=-128) #NOT USED?? #graymask = core.std.ShufflePlanes(clip, 0, colorfamily=vs.GRAY) #return graymask #AVS # Tweak( clip , float hue, float sat, float bright, float cont, # bool coring, bool sse, float startHue, float endHue, # float maxSat, float minSat, float interp, bool dither ] ) # Levels(clip input, # int input_low, float gamma, int input_high, # int output_low, int output_high # [, bool coring , bool dither ] ) # # std.Levels(clip clip[, float[] min_in, float[] max_in, float[] gamma=1.0, float[] min_out, float[] max_out, int[] planes=[0, 1, 2]]) #detailmaskpre0 = NOT USED?? d0 = orig.avs.mt_edge(thY1 = 3, thY2 = 255, thC1 = 255, thC2 = 255, mode = "cartoon", Y=3, V=1, U=1) d0 = adjust.Tweak(d0, hue=0.0, sat=1.0, bright=drange, cont=1.0) d0 = core.std.Levels(d0, min_in=60, gamma=dboost, max_in=255, min_out=0, max_out=255) d0 = core.std.Levels(d0, min_in=0, gamma=dboost, max_in=dlimit, min_out=255, max_out=0) detailmaskpre0 = d0.avs.mt_inflate(U=-128, V=-128).avs.mt_deflate().avs.mt_deflate().avs.mt_deflate() d1 = orig.avs.mt_edge(thY1 = 3, thY2 = 255, thC1 = 255, thC2 = 255, mode = "roberts", Y=3, V=1, U=1) d1 = adjust.Tweak(d1, hue=0.0, sat=1.0, bright=drange, cont=1.0) d1 = core.std.Levels(d1, min_in=60, gamma=dboost, max_in=255, min_out=0, max_out=255) d1 = core.std.Levels(d1, min_in=0, gamma=dboost, max_in=dlimit, min_out=255, max_out=0) detailmaskpre1 = d1.avs.mt_inflate(U=-128, V=-128) #Convolution(matrix=[1, 2, 1, 2, 4, 2, 1, 2, 1]) = blur(1) #detailmaskpre2 = clip.avs.mt_lut(detailmaskpre1, "x x * x * x * 256 / 256 / 256 /").std.Convolution(matrix=[1, 2, 1, 2, 4, 2, 1, 2, 1]).std.Levels(d1, min_in=60, gamma=dboost, max_in=255, min_out=0, max_out=255) clip = clip.avs.mt_deflate() #clip = core.std.ShufflePlanes(clip, 0, colorfamily=vs.GRAY) detailmask = clip white = orig.avs.mt_binarize(Y=-255,U=-128,V=-128) linemask1 = core.avs.mt_merge(white, detailmask, orig.avs.mt_invert()).avs.mt_invert() linemask = core.std.Levels(linemask1, min_in=0, gamma=1.0, max_in=255, min_out=0, max_out=strength) if(strength == 255): linemask = linemask1 sharp3 = sharp2 dark = core.avs.mt_merge(orig, sharp3, linemask, Y=3, U=1, V=1) darkmerged = core.std.ShufflePlanes(clips=[dark,orig], planes=[0, 1, 2], colorfamily=clip.format.color_family)#dark.avs.MergeChroma(orig) finaldark = darkmerged semifinal = orig.resize.Bicubic(twidth, theight, filter_param_a = 0, filter_param_b = 0.75) #, b=0, c=0.75 ?? final = dark.resize.Bicubic(ssw2, ssh2, filter_param_a = 0, filter_param_b = 0.75) final = Xsharpen(final, xstren, xthresh) final = final.resize.Bicubic(twidth, theight, filter_param_a = 0, filter_param_b = 0.75) final = core.std.ShufflePlanes(clips=[final,semifinal], planes=[0, 1, 2], colorfamily=clip.format.color_family)#avs.MergeChroma(semifinal) final = final.warp.AWarpSharp2(chroma=cwarp2, depth=wdepth, blur=wblur, thresh=wthresh) return final
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database Last edited by ChaosKing; 8th April 2017 at 14:36. |
8th April 2017, 15:57 | #7 | Link | |
Registered User
Join Date: Jun 2012
Location: Ibiza, Spain
Posts: 321
|
Quote:
Code:
last = unsharpmask(clip, 300, 4, 0) sharp = last last = core.std.MaskedMerge(sharp, clip, clip) sharp1 = last last = core.std.MaskedMerge(sharp1, clip, clip) sharp2 = last But anyway mftoon52 and mftoon54 look like a mess, a lot of code looks like leftovers or just buggy. |
|
8th April 2017, 16:36 | #8 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
hmm will try it
I just found v52 with comments here https://forum.doom9.org/showthread.p...851#post461851 This is missing in v54 Code:
## Add the two edgemasks together. YV12Layer(detailmaskpre2, detailmaskpre2, "mul", 255, chroma=false, Y=3, V=1, U=1).Levels(0, 1.0, 190, 0, 255) ConvertToYV12().Invert().Inflate().Invert() detailmask = last
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database |
8th April 2017, 17:05 | #9 | Link |
Registered User
Join Date: Jan 2016
Posts: 162
|
linemask
There's no need to use masktools of Avisynth for such code. Most of them can be implemented under vs standard library:
Take detailmaskpre0 as an example: Code:
detailmaskpre0 = orig.std.Convolution([0, -2, 1, 0, 1, 0, 0, 0, 0], planes=[0]).std.Expr(['x 3 < 0 x ? 255 > 255 x ?', '']) # mt_edge(thy1 = 3, thy2 = 255, thc1 = 255, thc2 = 255, mode = "cartoon", Y=3, V=1, U=1) detailmaskpre0 = detailmaskpre0.std.Expr(['x {} + 16 max 235 min'.format(drrange), '']) # Tweak(0.0, 1.0, drange, 1.0) detailmaskpre0 = Levels(detailmaskpre0, 60, dboost, 255, 0, 255) # Levels(60, dboost, 255, 0, 255) # The Levels() function is at havsfunc detailmaskpre0 = Levels(detailmaskpre0, 0, dboost, dlimit, 255, 0) # Levels(0, dboost, dlimit, 255, 0) detailmaskpre0 = detailmaskpre0.std.Inflate(0) # mt_inflate(u=-128, v=-128) detailmaskpre0 = detailmaskpre0.std.Deflate(0).std.Deflate(0).std.Deflate(0) # mt_deflate().mt_deflate().mt_deflate() Code:
detailmaskpre0 = orig.std.Convolution([0,-2,1,0,1,0,0,0,0], planes=[0]) detailmaskpre0 = detailmaskpre0.std.Expr(['x 3 < 0 x ? {} + 16 max 235 min'.format(drrange), '']) detailmaskpre0 = Levels(Levels(detailmaskpre0, 60, dboost, 255, 0, 255), 0, dboost, dlimit, 255, 0) detailmaskpre0 = detailmaskpre0.std.Inflate(0).std.Deflate(0).std.Deflate(0).std.Deflate(0) Code:
detailmaskpre1 = orig.std.Convolution([0,0,0,0,2,-1,0,-1,0], divisor=2, saturate=False, planes=[0]) detailmaskpre1 = detailmaskpre1.std.Expr(['x 3 < 0 x ? {} + 16 max 235 min'.format(drrange), ''])) detailmaskpre1 = Levels(Levels(detailmaskpre1, 60, dboost, 255, 0, 255), 0, dboost, dlimit, 255, 0) detailmaskpre1 = detailmaskpre1.std.Inflate(0) detailmaskpre2 = detailmaskpre1.std.Expr(['x x * dup * 16777216 /', '']) detailmaskpre2 = detailmaskpre2.rgvs.RemoveGrain([11, 0]) # Blur(1.0) last = sharp2.std.Deflate(0) detailmask = last white = orig.std.BlankClip(color=[255, 128, 128]) # orig.mt_binarize(Y=-255,U=-128,V=-128) linemask1 = white.std.MaskedMerge(detailmask, orig.std.Invert(0), planes=[0]).std.Invert(0) linemask = linemask1 if strength == 255 else Levels(linemask1, 0, 1.0, 255, 0, strength) Last edited by WolframRhodium; 9th April 2017 at 05:50. |
8th April 2017, 17:27 | #10 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
# Levels(60, dboost, 255, 0, 255)
# The Levels() function is at havsfunc Does that mean std.Levels from Vapoursynth is different from the Avisynth Levels? Or why should I use Levels from havsfunc instead of the build-in one?
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database Last edited by ChaosKing; 8th April 2017 at 17:31. |
8th April 2017, 18:21 | #11 | Link | |
Registered User
Join Date: Jan 2016
Posts: 162
|
Quote:
core.std.Levels() is a equivalent to Levels(coring=True) But by default, "coring" is False In addition, current core.std.Levels() is much slower than Levels() in havsfunc, because the former one has no optimization on speed, while the later one uses core.std.Lut() and runs very fast. Last edited by WolframRhodium; 8th April 2017 at 18:28. |
|
8th April 2017, 18:28 | #12 | Link |
Professional Code Monkey
Join Date: Jun 2003
Location: Kinnarps Chair
Posts: 2,548
|
Just a general note about this. You can probably combine several of the levels abd tweak calls into a single expr at least. Those old scripts usually are a redundant mess.
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet |
8th April 2017, 18:49 | #13 | Link | |
Registered User
Join Date: Jan 2016
Posts: 162
|
Quote:
but that would make the code even more messy, so I do not do that before people with good knowledge on this can do it themselves |
|
8th April 2017, 23:54 | #14 | Link | |
Registered User
Join Date: May 2014
Posts: 20
|
Quote:
Quick and dirty: Function Can probably be simplified but I dont't feel like wasting any more time on this shitty function. I looked at the function before the masktools2 port and fixed the detailmask. Use legacy=True to get the behaviour of v0.54, but this is not recommended. Actually, you shouldn't use this function at all. Works on any bitdepth. Last edited by Frechdachs; 9th April 2017 at 00:01. |
|
9th April 2017, 01:08 | #15 | Link |
Professional Code Monkey
Join Date: Jun 2003
Location: Kinnarps Chair
Posts: 2,548
|
I think the argumebt scaling is wrong for xsharpen and unsharpmask.
__________________
VapourSynth - proving that scripting languages and video processing isn't dead yet |
9th April 2017, 01:35 | #16 | Link | |
Registered User
Join Date: May 2014
Posts: 20
|
Quote:
Threshhold has to be scaled because it's compared to a difference and the difference will be bigger in 16 bit. Given that Code:
valuerange = (1 << clip.format.bits_per_sample) maxvalue = valuerange - 1 Code:
(x - y) * maxvalue // 255 equals x * maxvalue // 255 - y * maxvalue // 255 Last edited by Frechdachs; 9th April 2017 at 01:43. |
|
9th April 2017, 02:04 | #17 | Link |
Registered User
Join Date: Dec 2005
Location: Germany
Posts: 1,795
|
Wow thank you Frechdachs.
I was just about to go to bed and then this I made a quick test but noticed that the edges are kinda blurry. see here (avisynth uses strength=100) http://i.imgur.com/h9UZDdS.png
__________________
AVSRepoGUI // VSRepoGUI - Package Manager for AviSynth // VapourSynth VapourSynth Portable FATPACK || VapourSynth Database |
9th April 2017, 02:46 | #18 | Link |
Registered User
Join Date: May 2014
Posts: 20
|
Can't reproduce: https://diff.pics/AFmw9A7DgxNU/1
AviSynth and VapourSynth screens look exactly the same. Are you sure, you imported the right function? |
9th April 2017, 05:00 | #19 | Link | |
Registered User
Join Date: Jan 2016
Posts: 162
|
Quote:
I verify it on masktools-v2.0a48, not only by checking the source code but also run a practical test. Last edited by WolframRhodium; 9th April 2017 at 09:52. |
|
9th April 2017, 05:11 | #20 | Link | |
Registered User
Join Date: May 2014
Posts: 20
|
Quote:
I wrote this just with the information from there, never looked into the code: http://avisynth.nl/index.php/MaskTools2/Mt_edge (Also did you get my PM? I don't see anything in "Sent Items".) Edit2: Changed it. Last edited by Frechdachs; 9th April 2017 at 05:34. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|