Log in

View Full Version : Bezier easing function


sarimarton
24th July 2022, 23:20
Bezier function written for avisynth.

Example:


scripted = ScriptClip(part, """
x = float(current_frame) / float(len)
val = bezier(1, 0.55, 0.45, 1, 0.5)
overlay(blankclip(c, color=color), opacity=(val))
""", args="len,color,c", local=true)

https://gist.github.com/sarimarton/46decb1cd355df46fc5463468ced2bad

Reel.Deel
25th July 2022, 00:37
I tried using this function but I cannot get it to work. Also ScriptClip does not have the args parameter: http://avisynth.nl/index.php/ConditionalFilter#ScriptClip

Reel.Deel
25th July 2022, 03:36
I forgot about GRunT. So I got it to do something, but I don't think the output is correct:


Import("bezier-easing.avs")

c = ColorBars().Trim(0,100)
len = 50
color = $808080

scripted = ScriptClip(c, """
x = float(current_frame) / float(len)
val = bezier(1, 0.55, 0.45, 1, 0.5)
Last.overlay(blankclip(Last, color=color), opacity=(val))
""", args="len,color", local=true)

return scripted


Maybe @sarimarton can better explain on how to use it correctly.

Edit: StainlessS deleted his post and now it looks like I'm talking to myself :)

StainlessS
25th July 2022, 03:57
Yeh, I also talk to myself a lot. [dont know why, I never get a sensible reply]

After posting I tried it and realized that Args thing did not work for me either. [so I deleted post, to try embarrass Reel.Deel].

Anyways, this dont crash, but it dont do much either.


Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100)
c = part.invert.FlipVertical

len = 50
color = $808080

scripted = GScriptClip(part, """
x = float(current_frame) / float(len) # No idea what this is for
val = bezier(1, 0.55, 0.45, 1, 0.5)
Last.overlay(blankclip(c, color=color), opacity=(val))
""", args="len,color,c", local=true)

scripted

return Last


EDIT: I was gonna go to bed [03:58AM] but as I've just opened a can of cider, guess I'll havta wait a bit longer.

StainlessS
25th July 2022, 04:05
OK, this is I think what the x thing was supposed to do [maybe]


Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100)
c = part

len = 50
color = $808080

scripted = GScriptClip(part, """
x = float(current_frame) / float(len)
val = bezier(1, 0.55, 0.45, 1,x)
Last.overlay(blankclip(c, color=color), opacity=(val))
""", args="len,color,c", local=true)

scripted

return Last

Reel.Deel
25th July 2022, 04:16
OK, this is I think what the x thing was supposed to do [maybe]

I think so, it actually does something now. Most of it looks ok but I'm not sure why after the transition it starts to go back to the colorbars. C seems to not have any effect. Thanks for the help StainlessS, you redeemed yourself :p

StainlessS
25th July 2022, 04:21
Yep, c is just used for template clip to blankclip, ie pixel type and dimensions [so could just use part instead].

EDIT:
There seems to be something a bit strange happening in that script, Scriptclip should be ok with Args arg when Grunt installed.
I've seen that problem before, and was caused by something like Scriptclip calling Scriptclip, but there dont seem to be any scriptclip
in the bezier-easing.avs script. Its a bit spooky.

EDIT:
Maybe len=100, ie framecount better. [or maybe not]


Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100).ShowFrameNumber
c = part

len = part.Framecount
color = $8080F0

scripted = GScriptClip(part, """
x = float(current_frame) / (len-1) # Changed Float(len) to (len-1) : End with x = 1.0 on last frame
val = bezier(1.0, 0.55, 0.45, 1.0, x)
Last.overlay(blankclip(c, color=color), opacity=(val))
Subtitle(String(val),align=5) # Comment out
""", args="len,color,c", local=true)

scripted

return Last

StainlessS
25th July 2022, 05:49
Bit more play


Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100).ShowFrameNumber
c = part

len = part.Framecount
color = $8080F0
SHOW=True

scripted = GScriptClip(part, """
x = float(current_frame) / (len-1) # Changed Float(len) to (len-1) : End with x = 1.0 on last frame
val = bezier(1.0, 0.55, 0.45, 1.0, x)
Last.overlay(blankclip(c, color=color), opacity=(val))
if(SHOW) {
xval = current_frame * (1.0/(Framecount-1))
Subtitle("X=" + String(xval) + " : Y=" + String(val),Size=32,align=5)
x = Round(xval * (width-1) )
y = Round( Val * (Height-1))
y = (Height-1) - y # cartesian
Last.Overlay(c.BlankClip(length=1,width=5,height=5,Color=$FFFF00),x=x-2,y=y-2) # Dot Coord [5x5 : x,y offset by -(5/2) ie -2, center on middle pixel of 5x5 dot]
}
return last
""", args="len,color,c,SHOW", local=true)

scripted

return Last


@ Frame 50, ie halfway : Dot is at bottom end of green bar, below subtitle and above black. [ClickMe]
https://i.postimg.cc/p5LX3FN3/BEZ-00.jpg (https://postimg.cc/p5LX3FN3)

EDIT: Well thats the cider done, time for bye-byes.

Reel.Deel
25th July 2022, 06:23
Cool stuff StainlessS, setting len to the framecount seems to work as it should. I wonder if this bezier easing could be done in Expr, similarly to this (https://forum.doom9.org/showthread.php?p=1965462#post1965462).

Here's your last script in animated form:
https://i.ibb.co/mRLyxbB/avs-bezier.png


EDIT: Well thats the cider done, time for bye-byes.

Same here, it's bedtime :).

StainlessS
25th July 2022, 06:45
Dang, bit more cider.

Using Spline(), instead of Bezier thingy. Whacky Races :)

#Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100).ShowFrameNumber
c = part

len = part.Framecount
color = $8080F0
SHOW=True
CUBIC = True

scripted = GScriptClip(part, """
x = float(current_frame) / (len-1) # Changed Float(len) to (len-1) : End with x = 1.0 on last frame
#val = bezier(1.0, 0.55, 0.45, 1.0, x)
val = Spline(x, 0.0,0.0, 0.25,0.6, 0.3,0.5, 0.4,0.4, 0.5,0.7, 0.75,0.5, 0.8,0.25, 0.9,0.5, 1.0,1.0, cubic=Cubic)
Last.overlay(blankclip(c, color=color), opacity=(val))
if(SHOW) {
xval = current_frame * (1.0/(Framecount-1))
Subtitle("X=" + String(xval) + " : Y=" + String(val),Size=32,align=5)
x = Round(xval * (width-1) )
y = Round( Val * (Height-1))
y = (Height-1) - y # cartesian
Last.Overlay(c.BlankClip(length=1,width=5,height=5,Color=$FFFF00),x=x-2,y=y-2) # Dot Coord [5x5 : x,y offset by -(5/2) ie -2, center on middle pixel of 5x5 dot]
}
return last
""", args="len,color,c,SHOW,Cubic", local=true)

scripted

return Last


How yoo do dat dare animated ping ting ?

I wonder if this bezier easing could be done in Expr, similarly to this
I'm sure Wonkey could do that (such a showoff), but,
I guess if you note a few x and y coords in prev bezier version, you could maybe do reasonably similar with above spline whotsit.

Reel.Deel
25th July 2022, 07:02
Dang, bit more cider.

Using Spline(), instead of Bezier thingy. Whacky Races :)


https://i.ibb.co/vZFDp40/avs-bezier-spline.png


How yoo do dat dare animated ping ting ?

In VDub2, just save it as an animated PNG.


I guess if you note x and y coords in prev bezier version, you could maybe do reasonably similar with above spline whotsit.

I'm too dumb for that :D. Ok, now really bedtime

StainlessS
25th July 2022, 07:21
I changed [added to] the spline args, even a bit more whackier.

Dang, VDub does the animated ping, did not know that, tanks!


I'm too dumb for that
Yeh, so they say.

val = Spline(x, X1,Y1, X2,Y2, X3,Y3, X4,Y4, X5,Y5, ... Xn,Yn, .... Cubic=CUBIC)

Just pick a few of the sequential on-frame subtitled X,Y coord pairs from the post #8 script, and fill them into the "X1,Y1, X2,Y2, ... Xn,Yn, ... cubic=CUBIC"
above, and replace the whole spline() line in post #10.

StainlessS
25th July 2022, 08:14
OK, like this [probably could be better]

Spline part only

#Import("bezier-easing.avs")

part = ColorBars().KillAudio.Trim(0,100).ShowFrameNumber
c = part

len = part.Framecount
color = $8080F0
SHOW=True
CUBIC = True

scripted = GScriptClip(part, """
x = float(current_frame) / (len-1) # Changed Float(len) to (len-1) : End with x = 1.0 on last frame
#val = bezier(1.0, 0.55, 0.45, 1.0, x)
val = Spline(x, .0,.0, .1,.057721, .2,.121941, .3,.194941, .4,.280696, .5,.387326, .6,.536897, .7,.811531, .8,.961644, .9,.993541, 1.,1., cubic=Cubic)
Last.overlay(blankclip(c, color=color), opacity=(val))
if(SHOW) {
xval = current_frame * (1.0/(Framecount-1))
Subtitle("X=" + String(xval) + " : Y=" + String(val),Size=32,align=5)
x = Round(xval * (width-1) )
y = Round( Val * (Height-1))
y = (Height-1) - y # cartesian
Last.Overlay(c.BlankClip(length=1,width=5,height=5,Color=$FFFF00),x=x-2,y=y-2) # Dot Coord [5x5 : x,y offset by -(5/2) ie -2, center on middle pixel of 5x5 dot]
}
return last
""", args="len,color,c,SHOW,Cubic", local=true)

scripted
Subtitle("Spline")
return Last


result, Bezier top, spline bot
IMAGE REMOVED

EDIT:
Nah, mine aint animating on PostImage.org. [does OK in potplayer].
EDIT: If you click it twice to zoom, then it animates, but is too big to see properley.

EDIT: Try again, thumbnail
IMAGE REMOVED

Nah, try again full size
IMAGE REMOVED

try again with Gif thumbnail [ClickMe to view, Zoom, and save image]
https://i.postimg.cc/XXmdYkLD/Stacked.gif (https://postimg.cc/XXmdYkLD)
OK, thats it, PostImage.org dont like animated png.
Can click to see bigger animation.

EDIT: Still get that "Args is not an argument to scriptclip" when Import("bezier-easing.avs") commented out, and using ScriptClip instead of GScriptclip.
Still not sure whats going on there.

EDIT: There would be a DivideByZero above, if FrameCount == 1.
Also, I'm not sure if first and last frames should apply Opacity [Y] 0.0 and 1.0, or a bit above 0.0, and a bit below 1.0 ?
(ie, frame before frame zero should [sort of] apply 0.0, and frame after last frame should [sort of] apply 1.0, otherwise frame 0 and FrameCount-1 are not blended(not in transition) at all)
Maybe for better [closer to bezier] spline, x coords [with paired bezier Y coords] should be chosen which are closer together near inflexion points,
[or should it be further apart near inflexion points, not sure how that works, there must be an optimum way of choosing X,Y pairs for spline, probably on change in slope. One for those with reasonable calculus.]

StainlessS
25th July 2022, 20:24
OK, here has a few mods, showing slope (dy/dx).
Inflexion points are where slope transitions either side of 1.0.

DOSPLINE=True, make false for Bezier.

ColorBars().KillAudio.Trim(0,100).ShowFrameNumber
# Got rid of part and c clips, and len

color = $8080F0
DOSPLINE = True # True use Spline else Bezier
CUBIC = true # For Spline Only
SHOW = True

DOSPLINE ? NOP : Import(".\bezier-easing.avs") # Import only if NOT DOSPLINE.

Function BezFunc(float x,bool "UseSpline", Bool "Cubic") {
UseSpline = default(UseSpline,false)
Return (UseSpline)
\ ? Spline(x, 0.0,0.0, 0.1,0.057721, 0.2,0.121941, 0.3,0.194941, 0.4,0.280696, 0.5,0.387326, 0.6,0.536897, 0.7,0.811531, 0.8,0.961644, 0.9,0.993541, 1.0,1.0, cubic=Default(Cubic,true))
\ : Bezier(1.0, 0.55, 0.45, 1.0, x)
}


GScriptClip(Last, """
xNorm = current_frame * (1.0/(Framecount-1)) # x Normalized coord, range 0.0 -> 1.0
YNorm = BezFunc(xNorm,DoSpline,Cubic) # y Normalized coord, range 0.0 -> 1.0
Last.overlay(blankclip(Last, color=color), opacity=(YNorm))
if(SHOW) {
xNorm2 = (current_frame+1) * (1.0/(Framecount-1)) # x Normalized coord @ current frame + 1
YNorm2 = BezFunc(xNorm2,DoSpline,Cubic) # y Normalized coord @ current frame + 1
xd = xNorm2 - xNorm # xd = change in Normalized x
yd = YNorm2 - YNorm # yd = change in Normalized y
# Inflexion points are where slope changes from below 1.0 to above 1.0 and above 1.0 to below 1.0.
Slope = yd / xd # dy/dx = slope
Subtitle("X=" + String(XNorm) + " : Y=" + String(YNorm) + " : dy/dx=" + String(Slope),Size=24,align=5)
xPhy = Round(xNorm * (width-1) ) # Cartesian X to Physical X coord
yPhy = (Height-1) - Round(yNorm * (Height-1)) # Cartesian Y to Physical Y coord : Phyical Raster Y coord [Cartesian Y=0 is at raster height-1, bottom of frame, not top]
# Dot Coord [5x5 : x,y offset by -(5/2) ie -2, center on middle pixel of 5x5 dot]
# NOTE, x=xPhy-2,y=yPhy-2 : The -2 offsets are both physical, ie left and up. [Overlay x,y coords are of top/left pixel of 5x5 block].
Last.Overlay(Last.BlankClip(length=1,width=5,height=5,Color=$FFFF00),x=xPhy-2,y=yPhy-2)
}
return last
""", args="color,DOSPLINE,CUBIC,SHOW", local=true)

Subtitle((DOSPLINE)?"Spline":"Bezier")

return Last

EDITED: Change names of two variables.

[ClickMe]
https://i.postimg.cc/rKBC4VcW/Stacked.gif (https://postimg.cc/rKBC4VcW)