Log in

View Full Version : GScript - language extensions for Avisynth


Pages : [1] 2

Gavino
18th June 2009, 11:18
This is something I started as a 'proof of concept' for my own amusement.
As I think some people will find it useful, I am making it generally available.

GScript is a plugin that extends the Avisynth scripting language to provide additional control-flow constructs:
multi-line conditionals (if-then-else blocks), 'while' loops and 'for' loops.
Rather than trying to simulate these constructs with functions, GScript effectively extends the language syntax, making it easy to use the new constructs in a natural way and in arbitrary combinations.

Here are the constructs in detail:

'if' statement
if ( condition ) {
statements
}
else {
statements
}
where condition is any boolean expression.
The statements can be any Avisynth statements, including the GScript extensions themselves, and so the new constructs can be nested.
The else part may be omitted (equivalent to else {}).

GScript also provides the 'else if' construct (optionally repeated to create a chain of conditionals). Thus
if ( condition ) {
statements
}
else if ( condition ) {
statements
}
else if (...) { ... }
...
else {
statements
}
'while' loop
while ( condition ) {
statements
}
The statements are repeated while the condition is true.

Example:
while (Height() < h) {
StackVertical(last, c)
}
'for' loop

for ( variable = init , limit , step ) {
statements
}

init, limit and step are integer expressions, with step non-zero. step is optional and defaults to 1.

First the variable is set to the value of init.
The statements are repeated until the exit condition is met,
ie variable exceeds limit (if step > 0), or is less then limit (if step < 0).
After each iteration, variable is incremented by step.
If the initial value satisfies the exit condition, the number of iterations will be zero.

Example:
for (i=1, nBlurs) {
Blur(0.5)
}
Using GScript
Once the plugin is loaded (either via LoadPlugin or by installing GScript.dll in your plugins folder), there are two ways to use the extended language features.
Firstly, a script (or part of a script) containing extensions can be passed as a text string to the GScript function (similar to the way functions like ScriptClip or MT are used). For example,
GScript("""
if (i > 10) {
x = 1
y = 2
z = 3
}
else {
x = 4
y = 5
z = 6
}
""")
The second way is to use the GImport function, which reads the entire contents of a file. This is similar to the standard Import, but supports the use of GScript extensions directly in the file.
The advantage of this is that you don't have to put quotes around the script, or worry about possible problems if the embedded script itself contains both triple and single quotes.
Thus, you can write entire scripts directly in the extended language and just pass to Avisynth a single GImport command to read it.
GImport("MyGScript.avs")
For completeness, there is also a function GEval, analagous to the standard Eval, which evaluates an arbitrary string that is permitted to contain GScript extensions.

Update: Version 1.1 (GScript_11.zip) released 6th Dec 2009

J_Darnley
18th June 2009, 11:51
Good god man! This is brilliant.

leeperry
18th June 2009, 13:48
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?

Didée
18th June 2009, 14:11
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?
Sure, it could. You could also buy a laser beam cutting machine when you need to cut a piece of paper. :eek:

For *such* a simple task, Avisynth's standard language (conditional operation through bool ? this : that) is fully sufficient ...

src = last

dest_modulo = 2 # or 4, 6, 8, 1337, ...
src_modulo = src.width()%dest_modulo
padding = dest_modulo - src_modulo

src_modulo==0 ? src : src.addborders(0,0,padding,0)

Gavino
18th June 2009, 14:20
nice! so basically this could be used w/ mod2 only scripts? if not mod2 > add padding lines?
Yes, although you could probably do this just as easily with the standard conditional operator (http://avisynth.org/mediawiki/Operators)(... ? ... : ... ).
EDIT: as Didée has just shown!

Where the extended 'if' becomes really useful is when you need to write more than one statement in one of the conditional 'branches'.
Without GScript, you are limited to the rather messy techniques described here (http://avisynth.org/mediawiki/Block_statements), which can't be easily nested. See also here (http://avisynth.org/stickboy/ternary_eval.html).

Archimedes
18th June 2009, 14:31
If then constructs can also be realized in this way.

isYV12() ? Eval("""
# do
# something
""") : Eval("""
# do
# something
""")

tin3tin
18th June 2009, 15:58
Very nice indeed! :) This way of coding in a more readable syntax(plus the extra functions) is more that welcome. One could hope that this would eventually be implemented in Avisynth so the quotes around the script would not be needed at all.

leeperry
18th June 2009, 18:00
hehe ok thanks fellas, as we say in France "caviar doesn't taste better w/ a big spoon"...ideally I'd love to an automatic script that'd make everything mod2 in ffdshow by simply adding horizontal black bars *only* if required, I'll look into Didée's script :cool:

mikeytown2
18th June 2009, 20:39
Gavino, thanks for doing this! It makes script development a lot simpler now :)

shoopdabloop
18th June 2009, 21:04
finally, as an actionscript 3 programmer, i can feel a little more comfortable in avisynth.

Gavino
19th June 2009, 17:16
One could hope that this would eventually be implemented in Avisynth so the quotes around the script would not be needed at all.
If the extensions gain sufficient acceptance, it would be fairly trivial to put them into the Avisynth core.

To implement the plugin, I used a modified version of the Avisynth parser code. The changes are relatively self-contained and all clearly marked in my source code. It would take little more than a cut-and-paste job to put those changes into the 'real' parser.

tin3tin
25th June 2009, 23:50
(I know that it ain't xmas - but imagine what you could do with those functions combined with two new functions(just idears): one to paint a pixel(x,y,color) and one to read the color of a pixel(x,y) then the more complicated imagemanipulation filters could be prototyped in avisynth.:))

Anyway thanks again for the Gscript plugin. :)

tin3tin
18th September 2009, 21:25
A bunch of gradients done with gscript. :)

Uncomment the various Gradient lines to check them out:
loadplugin("GScript.dll")

function Gradient(int gwidth, int gheight, int ared, int agreen, int ablue, int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
blankclip(1,gwidth,1)
GScript("""
for (i=1, gheight,1){
r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,true)/float(gheight)*255)
g=int(spline(i,0,agreen,int(gheight/2),bgreen,gheight,cgreen,true)/float(gheight)*255)
b=int(spline(i,0,ablue,int(gheight/2),bblue,gheight,cblue,true)/float(gheight)*255)
c=blankclip(1,720,1,color=r*65536 + g*256 + b)
StackVertical(last, c)
}
""")
crop(0,1,0,0)
}
function GradientNoSpline(int gwidth, int gheight, int ared, int agreen, int ablue, int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
blankclip(1,gwidth,1)
GScript("""
for (i=1, gheight,1){
r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,false)/float(gheight)*255)
g=int(spline(i,0,agreen,int(gheight/2),bgreen,gheight,cgreen,false)/float(gheight)*255)
b=int(spline(i,0,ablue,int(gheight/2),bblue,gheight,cblue,false)/float(gheight)*255)
c=blankclip(1,720,1,color=r*65536 + g*256 + b)
StackVertical(last, c)
}
""")
crop(0,1,0,0)
}

#Gradient(720, 576,86,107,103,184,164,126,140,36,29)#Vintage America
#Gradient(720, 576,59,61,40,113,117,76,255,113,68)#Dawn
#Gradient(720, 576,160, 88, 50, 209,169, 75, 249,209,140)#fruity
#Gradient(720, 576,225,230,250,171,200,226,24,49,82)#Blue
#Gradient(720, 576,236,224,158,145,134,90,191,62,47)
#Gradient(720, 576, 62,102,51,220,240,242,150,35,9)#GreenBlueRed
#Gradient(720, 576,62,153,96,159,235,74,237,255,116)#Greenish
#Gradient(720, 576,117,0,0,215,215,215,0,100,200)#BleuBancRouge
#Gradient(720, 576,178,255,0,194,194,194,255,96,10)#GreenBlueRed
#Gradient(720, 576,118,192,245,223,236,245,245,105,198)#Baby
#Gradient(720, 576,118,192,245,255,170,85,255,0,0)#Sunset
#Gradient(720, 576, 17,0,28,94,0,30,17,9,28)#RedPurple
#Gradient(720, 576, 6,171,170,5,91,161,0,28,54)#Deep Ocean
#Gradient(720, 576,217,204,143,109,140,42,37,64,25)#Grassy Fields
#Gradient(720, 576,103,57,15,217,139,43,42,23,12)#Brown
#Gradient(720, 576,178,150,82,255,94,53,166,222,161)#OrangeGreen
#Gradient(720, 576,249,209,147,75,83,106,193,90,55)#Blue Evening
GradientNoSpline(720, 576,121,121,59,216,186,72,51,7,6)#Red jungle

Gavino
19th September 2009, 09:47
Thanks, tin3tin. A good example of how GScript makes this sort of thing easier to write.

Of course, it can also be done in standard Avisynth by using recursive procedures, but most people would find it more natural to write an iterative construction like this directly as a loop.

Note that the GScript call need not be confined to the 'non-standard' parts of the script. For example, each function (or even both together) could be put inside GScript. This way, the GScript parser is invoked only once, rather than on each call to the function.

For example,
GScript("""
function Gradient( ... ) {
...
}

function GradientNoSpline( ... ) {
...
}
""")

tin3tin
19th September 2009, 09:56
Will that make it faster? As it is this gradient function is properly too slow(thanks to stackvertical?) to be really useful.

Gavino
19th September 2009, 10:48
In principle, moving the GScript to outside the function declaration will speed up compilation of the function calls (and hence script loading), but the difference is unlikely to be noticeable. It doesn't affect the 'run-time' - GScript acts purely at 'compile-time'.

I'm not sure if the slowness here comes from the StackVertical or the Spline function - I will look into it and see if it can be made faster in some way.

In your code
r=int(spline(i,0,ared,int(gheight/2),bred,gheight,cred,true)/float(gheight)*255)
... etc ...
why do you effectively multiply by 255/gheight?
I get better results with just r=int(spline(...))

tin3tin
20th September 2009, 09:30
why do you effectively multiply by 255/gheight?
I get better results with just r=int(spline(...))
You're right, that's just a leftover from previous attempt I forgot to clean out.:)

Gavino
20th September 2009, 17:04
tin3tin - Looking at this more closely, I think the overhead is due to the repeated use of StackVertical. For an image height of 576, you have 576 instances of StackVertical, each copying an average of 288 lines, so that's over 150000 lines being copied!

A faster way would be to directly use a resizer as the interpolator instead of the Spline function. Try these alternative versions which should produce similar results to yours (I believe identical in the non-spline case).
function Gradient2(int gwidth, int gheight, int ared, int agreen, int ablue,
\ int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
c1 = BlankClip(1, gwidth, 3, color=ared*65536 + agreen*256 + ablue)
c2 = BlankClip(1, gwidth, 1, color=bred*65536 + bgreen*256 + bblue)
c3 = BlankClip(1, gwidth, 3, color=cred*65536 + cgreen*256 + cblue)
StackVertical(c1, c2, c3)
Spline16Resize(gwidth, gheight, 0, 2.5, 0, -2.5)
}

function GradientNoSpline2(int gwidth, int gheight, int ared, int agreen, int ablue,
\ int bred, int bgreen, int bblue, int cred, int cgreen, int cblue)
{
c1 = BlankClip(1, gwidth, 2, color=ared*65536 + agreen*256 + ablue)
c2 = BlankClip(1, gwidth, 1, color=bred*65536 + bgreen*256 + bblue)
c3 = BlankClip(1, gwidth, 2, color=cred*65536 + cgreen*256 + cblue)
StackVertical(c1, c2, c3)
BilinearResize(gwidth, gheight, 0, 1.5, 0, -1.5)
}
Here, GScript is no longer required, but I think it is fair to say that the problem lay not with GScript itself but with the method you used.

(BTW there was another bug in your original code, where 720 was used in place of gwidth in the BlankClips.)

tin3tin
21st September 2009, 08:29
Wow, that's clever - and fast!

Before it was impossible(too slow) to make a gradient lib like this(using 3 out of 5 colors from Kuler (http://kuler.adobe.com/)):
Gradient(720, 576,86,107,103,184,164,126,140,36,29).Subtitle("Vintage America", align=2,text_color=$FFFFFF)#Vintage America
last+Gradient(720, 576,59,61,40,113,117,76,255,113,68).Subtitle("Dawn", align=2,text_color=$FFFFFF)#Dawn
last+Gradient(720, 576,160, 88, 50, 209,169, 75, 249,209,140).Subtitle("Red Yellow Pink", align=2,text_color=$FFFFFF)#Red Yellow Pink
last+Gradient(720, 576,225,230,250,171,200,226,24,49,82).Subtitle("Blue", align=2,text_color=$FFFFFF)#Blue
last+Gradient(720, 576,236,224,158,145,134,90,191,62,47).Subtitle("White Green Red", align=2,text_color=$FFFFFF)#White Green Red
last+Gradient(720, 576, 62,102,51,220,240,242,150,35,9).Subtitle("Green White Red", align=2,text_color=$FFFFFF)#GreenWhiteRed
last+Gradient(720, 576,62,153,96,159,235,74,237,255,116).Subtitle("Greenish", align=2,text_color=$FFFFFF)#Greenish
last+Gradient(720, 576,117,0,0,215,215,215,0,100,200).Subtitle("Bleu Banc Rouge", align=2,text_color=$FFFFFF)#BleuBancRouge
last+Gradient(720, 576,178,255,0,194,194,194,255,96,10).Subtitle("Green Blue Red", align=2,text_color=$FFFFFF)#GreenBlueRed
last+Gradient(720, 576,118,192,245,223,236,245,245,105,198).Subtitle("Baby", align=2,text_color=$FFFFFF)#Baby
last+Gradient(720, 576,118,192,245,255,170,85,255,0,0).Subtitle("Sunset", align=2,text_color=$FFFFFF)#Sunset
last+Gradient(720, 576, 17,0,28,94,0,30,17,9,28).Subtitle("Red Purple", align=2,text_color=$FFFFFF)#RedPurple
last+Gradient(720, 576, 6,171,170,5,91,161,0,28,54).Subtitle("Deep Ocean", align=2,text_color=$FFFFFF)#Deep Ocean
last+Gradient(720, 576,217,204,143,109,140,42,37,64,25).Subtitle("Grassy Fields", align=2,text_color=$FFFFFF)#Grassy Fields
last+Gradient(720, 576,103,57,15,217,139,43,42,23,12).Subtitle("Brown", align=2,text_color=$FFFFFF)#Brown
last+Gradient(720, 576,178,150,82,255,94,53,166,222,161).Subtitle("Orange Green", align=2,text_color=$FFFFFF)#OrangeGreen
last+Gradient(720, 576,249,209,147,75,83,106,193,90,55).Subtitle("Blue Evening", align=2,text_color=$FFFFFF)#Blue Evening
last+GradientNoSpline(720, 576,121,121,59,216,186,72,51,7,6).Subtitle("Red jungle", align=2,text_color=$FFFFFF)#Red jungle

The next big challenge is how to make a smooth gradient in yv12.

Gavino
21st September 2009, 14:13
The next big challenge is how to make a smooth gradient in yv12.
I suppose you mean something other than just adding ConvertToYV12()? :)
Perhaps starting out with yuv values as the arguments instead of rgb?

Note that BlankClip has a color_yuv parameter, so I think you can just do something similar to the rgb version, using pixel_type="YUY2", and convert to YV12 after the resize.

Gavino
7th December 2009, 00:36
This is an update to fix a few problems. A minor extension regarding comments is also included.

Bugs fixed:
- On some systems, a crash would occur when GScript attempted to report any kind of error (eg syntax error or Assert failure).
- In a 'while' loop, the conditional test was evaluated before any implicit assignment to 'last' on the final statement of the block, potentially causing the wrong value of 'last' to be used in the condition.
- When incrementing a 'for' loop variable at the end of the loop body, any user assignments to the variable in the body were ignored.

New extension:
- Within GScript, comments are allowed before a '{'.
This applies not only in the GScript constructs (if, etc), but also to standard uses of '{' in function declarations and try/catch. Arguably, it is a bug that Avisynth itself does not permit this (see this thread).

Get the latest version from the first post in this thread.
For a limited period, also available here:
http://www.sendspace.com/file/9cfhfp

StainlessS
19th December 2009, 14:48
This is my new bestest plugin, thanx Gavino,

Thought you might like to know I've posted a little script:-

http://forum.doom9.org/showthread.php?p=1354574#post1354574

Using GScript, uses a recursive function, tried it up to about 140 levels
of recursion without probs, assume that it is a dynamic heap type stack
rather than a real one in Avisynth.

Anyways, LOVE THIS, everyone shoud get this for XMAS.

PS, where can I get one of these fabled Paper cutting laser machines? :)

Gavino
19th December 2009, 17:48
Thanks, StainlessS. Interesting example.

Although it doesn't actually seem to be a problem, you could eliminate the recursive call to GScript itself by defining the entire function within GScript, ie
GScript("""
Function __FPS_23_to_24__(clip Last)
{
...
}
""")

Of course, the function itself would still be recursive.
I wondered if that recursion could be easily removed by using a 'while' loop, but I think your algorithm is easier to express recursively, as you have done.

StainlessS
19th December 2009, 20:31
@ Gavino,

I shall edit the GScipt(""" stuff to outside the function, thought it was purely compile time.

After getting it working recursively, I did spend about 10 mins converting using while loop, but
thought, 'sod it, why bother'. It can be more difficult than recursive, the iterative Euclid() thing
runs quite a lot quicker than rercursive, and in Knuth, (maybe Fundamental Algorithms) he
does a fairly longer iterative version that is quite a bit faster than that. If it could be converted
to iterative, it would not be too difficult a job to make it run without GScript (Eval), but would
not want to even try doing it that way without something that already worked.

I have not really done any coding [other than my new filter Exblend() as posted on doom Dec 2nd],
for about 14 years. Did quite a bit of graphics type stuff, quick drawing of lines, circles, ellipse,
torus etc, using something called DDA. Cannot for the life of me remember what its called [DDA],
nor anything about how it works. Was thinking that maybe I could use it [DDA] in doing a direct
conversion from 23.976 to 25 FPS (instead of a 24FPS interim conversion).
Could you please take a quick look at the below comments from a function I wrote about 16 or 17
years ago, I cant make head nor tail of it and dont even know what to look for on the net,
looked DDA up on Wikipedia, got something completely unrelated.

See Below:-



void wrcircle0(int xc,int yc,int r,int pen)
{
/* circle
Single pixel render version (ie wrpixel()).
Draw a lovely round circle on a 1:1 aspect ratio device using a DDA.
Uses equation of circle:-
x*x + y*y <= r*r
where pixel is exactly on circumference of circle when the
equation balances exactly.
We wish for rounding to the nearest pixel using the distance from the
origin to the circumference ie
sqrt(x*x + y*y) <= r + 0.5
The above in effect calculates the distance from the centre of the
origin to the centre of the target pixel (ie the coords themselves are
NOT rounded, simply the distance from centre to centre) and it is the
radius that is rounded rather than the x,y coords.
We need the pixel that provides the greatest distance from the
origin while maintaining the above relationship.
We want to re-write in the form of the first equation so
x*x + y*y <= (r + 1/2)*(r + 1/2)
Expanding the right hand side we get
x*x + y*y <= r*r + r + 1/4
As (x*x + y*y) never produces a fractional result, we can drop the 1/4
from the equation without affect.
Rewriting:-
x*x + y*y - r*r - r <= 0
where ((r*r) - r) is constant and (x*x) and (y*y) vary
and can be calculated easily without multiplication as we step
through the x,y coordinates.
Where
n -1 0 1 2 3 4
(n*n) -1 0 1 4 9 16
(n*n)-((n-1)*(n-1)) -1 1 3 5 7
diffstep 2 2 2 2

The difference (n*n) - ((n-1)*(n-1)) cancels to:-
2n - 1 and varies by diffstep (2) when stepping through x,y coords.
The threshhold at x,y of (0,r) is calculated as
(0*0) + (r*r) - (r*r) - r which cancels to (-r).
We step coords clockwise from top centre (0,r) to (r,0). We check
first that x+1,y is ok to print and if so we move RIGHT (From our
rotation and the perfect aspect ratio, the pixel to the right of current
is ALWAYS further away and always furthest possible if plottable), if
this fails then we KNOW we have to check 1 DOWN and RIGHT of current as
this is always next possible longest radius, if plottable we move DOWN
and RIGHT, otherwise we KNOW that 1 down from current is always closer
than current so we do not need to check whether its plottable and so we
move DOWN.
The above method ensures that plotted points are no more than 1
pixel from the previous one (counting diagonal as one) and so leaves
no gaps in the circle.
To save complications, when plotting 4 quadrants we plot in 2
parts, the initial top and bottom middle pixels are plotted first
and it then loops to find the next coords, plots two of those and waits
until the next loop to do the same coords in the other quadrants.
This removes the necessity to plot the top, bot, left, and right centre
pixels as special cases (Otherwise plots same pixels twice).
Have tested from radius 1 to 1500 and NO pixels overlap any other
plotted pixels therefore not affecting XOR type operations.
DONT CHANGE algorithm without good cause.
Further, To calculate the upper coord of the vertical cord where x==r
we use:-
y*y <= (r*r) + r + 1/4 - (x*x)
As (x == r) and 1/4 will not take any significance we rewrite as:-
y*y <= r OR y = (int)sqrt(r); (Fract part discarded)
This algorythm does produce the occasional extra pixel at 45 degrees
which results in a pointy bit instead of a smooth diagonal, however,
as there are only about 5 instances with a radius less than 10,000 and
only 4 less than 1000 radius (ie 1, 8, 49, 288). We we could eradicate
this but do not due to the overhead of detection for such a small
improvement. [ if((thresh <= 0)&&((x+1)!=y)) step right ELSE step left].
NOTE, At radius == 1, the aforesaid pointy bit is desired.
*/
long thresh; /* Needs long (ranges about +- 2r ) */
long xd; /* Needs long (ranges about -1 to 2(r+1) - 1) */
long yd; /* Needs long (ranges about -1 to 2r - 1) */
int x,y,terminate,tem;
const long diffstep = 2L; /* long to avoid size extension */
if (
(r<=0) ||
((yc-r) > clip[3]) ||
((yc+r) < clip[1]) ||
((xc-r) > clip[2]) ||
((xc+r) < clip[0])
)return;
/* Clip thresh, (-ve if fully within clipping area ) */
if((terminate=clip[1]-yc)<(tem=yc-clip[3]))
terminate = tem;
x=0;y=r; /* Preset plot at (0,r) and init thresh for (1,r) */
yd = (2L*r - 1L); /* yd(r) */
xd = (2L*0 - 1L + 2L); /* xd from 0 to 1 */
thresh = (-r); /* thresh(0,r) */
thresh += xd; /* thresh(1,r) */
while((y > 0)&&(y >= terminate))
{
wrpixel(xc + x ,yc - y,pen,NULL); /* quad 1 (And starting plot) */
wrpixel(xc - x ,yc + y,pen,NULL); /* quad 3 (And starting plot) */
if(thresh <= 0) /* Can we do (x+1,y), 1 to RIGHT of current */
{ /* Yes, step x Right */
xd += diffstep; /* xd from x+1 to x+2 */
thresh += xd; /* thresh(x+2,y) */
++x; /* This is longest poss radius, DONE */
}
else
{ /* No, stepping y Down */
thresh -= yd; /* thresh(x+1,y-1) */
yd -= diffstep; /* yd from y to y-1 */
if(thresh <= 0)/* Can we do (x+1,y-1), 1 dwn, 1 RGT of current */
{ /* Yes, stepping both DOWN and RIGHT */
xd += diffstep; /* xd from x + 1 to x + 2 */
thresh += xd; /* thresh(x+2,y-1) */
++x;
}
--y; /* Dont forget to DOWN step y */
}
wrpixel(xc - x ,yc - y,pen,NULL); /* quad 2 (And closing plot) */
wrpixel(xc + x ,yc + y,pen,NULL); /* quad 4 (And closing plot) */
}
}


Any of that mean anything to you? Beats the hell out of me what it is. :)

PS, Seem to remember that the DDA thing tends to use
XD, YD and Diffstep, whether in line drawing or any other use.

Gavino
19th December 2009, 21:17
I shall edit the GScipt(""" stuff to outside the function, thought it was purely compile time.
It is (like all recursion and function calls in Avisynth), but inside the function, GScript gets re-evaluated on each recursive call, so it potentially affects script loading time (and stack usage during this phase) - perhaps not noticeably.

I'm preparing for a trip at the moment, so I don't have time to study your circle algorithm right now. Is it related to Bresenham's circle algorithm (http://en.wikipedia.org/wiki/Midpoint_circle_algorithm)? I don't see the connection with frame-rate conversion though. :confused:

StainlessS
19th December 2009, 23:11
Bresenham's circle algorithm,

That seems to ring a bell and probably is similar in some
respects (probably even based on), however, the circle
algo I posted was unlike any other currently used on any
platform. At one time there were competing graphical
models floating about and most platforms settled on the
same model. Things like not plotting the last pixel of a line.
The included circle routine plots absolutely lovely round
circles even at small sizes but does not fit in the accepted
model. A similar sized circle done with this compared to
one drawn in windows looks well different. I think part of it
is that my circle judges the origin to be in the centre of
the pixel, whereas the accepted model (rounding to
x,y coordinates) effectively puts the origin in the
bottom left corner (depending upon coordinate system
used). [At least thats what seems to be coming back to me].

EDIT:- Got the above circle center thing completely back to
front.
Anyways, I think there was summick called Bresenhams
line algorithm, and I think that, that is the thing I was
looking for. It uses a DDA, (whatever that means) to draw
eg diagonal lines, stepping regularly on one axis and every
now and again, taking a step on the alternate axis. As you
say, it may be of no use at all in this instance, but i
could not remember how it worked. Will look at your link,
try and figure out the DDA thing, might just have to use
floating point instead, inserting a sysnthesized frame every
23.4140625 input frames.

Thankyou for taking the time to point out Bresenham, he
is exactly the guy I was looking for, I think. Please enjoy
your holiday and dont bother with the circle thing, you given
me every thing I need to find what I am looking for.

Ta very much

Byesey bye
:)

don't see the connection with frame-rate conversion though. :confused:

EDIT:- Yeah, your right, complete wild goose chase, thanx for your time. :thanks:

Gavino
25th March 2010, 11:53
Stephen - thanks for your suggestions. I will need to think about them before giving a full answer.

In the meantime:
- a crude way to force exit from a loop is to set the loop counter to its final value;
- you might want to look at the array features in AVSLib (http://avslib.sourceforge.net).

Gavino
1st April 2010, 16:46
I'm still thinking about it. :)
Neither feature is completely trivial, but on the other hand they're not totally infeasible either.

My current thinking is that arrays would require further support from the core to be worth having, eg ability to use them as function arguments. So the break/continue feature seems a more likely GScript candidate.

I think this could be done, but before expending more effort, I'd like to know how much of a demand there is for this. Note that the effects of break/continue can in principle already be achieved using if/else and appropriate boolean flags in your (G)script.
What do you think, good users?

jinkazuya
17th October 2010, 15:15
Yes...hope there would be more plugin and make avisynth work like OOP, which is much easier to understand. Thanks a lot Gavino, you are a hero.

prokhozhijj
20th February 2011, 01:49
Does someone has intention to embed GScript to Avisynth? I think it will be very useful.

wiseant
21st October 2014, 04:34
Hi
Hope this is the right place to post this question

Hi

let's say I have a number of subtitles
c0="Hello World"
c1="Hello and GoodBye"
c2="Love is all you need"
c3="avisynth rocks"
c4="Gscript is awesome"


and I want to call these subtitles (variables) in a loop, where the value of k represents a different clip or image being processed in the loop and I want to add each subtitle

I can use this syntax to use subtitle c0

k=k.subtitle(c0, 8,460)

but how do I use this if I want to use the values of c0, c1, etc

I have been trying something like this

caption= "c" + string(i)
k=k.subtitle(caption,8,460)

this give me text strings "c0", "c1", "c2", . . .
but I want to get the "value" of c0, c1, c2, etc

I tried using

caption= eval("c" + string(i))

but I get "Script Error - invalid arguments to function "Subtitle""


TIA

wiseant
21st October 2014, 05:08
I forgot to use subtitle(string(Caption))

so this code works


caption = Eval("c"+String(i))
k=k.subtitle(string(Caption), 8, 460)

Gavino
21st October 2014, 09:02
Hi, wiseant.

You shouldn't need to use string(), as caption is already a string.
This works fine for me:

c1 = "Hello"
i = 1
caption = Eval("c"+string(i))
BlankClip().Subtitle(caption)

wiseant
21st October 2014, 20:35
Hi Gavino

Yes,

caption = Eval("c"+string(i))

that does work - when I tried it yesterday I received the error message - probably because I had more images than captions

StainlessS
21st November 2014, 01:53
Why is this thread so, so, so, under posted.
The only reason I can think of is that GScript is so perfect, that nobody can find anything to complain about.

Come-on TheFluff, you like to have a good complain about things, complain about this so we can retaliate and get its post count up.

fvisagie
25th November 2014, 21:29
{:-)]

Seedmanc
17th March 2016, 18:20
Is there a 64bit version of GScript or do I have to move to AVS+ for that? If the latter, does it support ScriptClip or other means of accessing current_frame?

Dreamject
25th May 2019, 20:44
Why do avisynth devs not include this in avisynth? Original syntax is nightmare especially unhighlighted eval("""""")

manolito
25th May 2019, 21:00
Gscript is integrated into AVS+ already, and for classic AVS it looks like development has ended...

GScript (a plugin for AviSynth that provides new control-flow constructs such as loops) has been incorporated natively into AviSynth+. Syntax is mostly unchanged, with two notable differences:
In AviSynth+ there is no need to wrap your GScript code in a string. The language extensions are native to AviSynth+ and can be used transparently.
The "return" statement has been changed to not only exit the GScript code block, but behaves like a normal AviSynth return statement: it causes the termination of the active script block (user function), or if not in a function, the entire script.

Dreamject
25th May 2019, 21:17
Gscript is integrated into AVS+ already,
https://img1.thelist.com/img/gallery/what-happens-to-your-body-when-you-cry/intro-1525376112.jpg

Dreamject
25th May 2019, 21:40
It's not mentioned in http://avisynth.nl/index.php/Block_statements
So it looks like purple text with limitations
https://s17.directupload.net/images/190525/eqss48a4.png

StainlessS
26th May 2019, 00:09
http://avisynth.nl/index.php/AviSynth%2B#GScript
http://avisynth.nl/index.php/Avisynthplus_color_formats
http://avisynth.nl/index.php/Convert
http://avisynth.nl/index.php/ConvertBits
http://avisynth.nl/index.php/Expr
http://avisynth.nl/index.php/High_bit-depth_Support_with_Avisynth

Dreamject
26th May 2019, 01:15
People search keyword and read what them need. Only today I read that doom9 is 'for everyone interested in DVD conversion.'.

I dont remember I met if then else construction in any example. Suggesting to use eval(""" """) and ignore that if then else exist is mockery of people. Or if you need something like
If x>1 {
a=2
b=3
if y>0 {
c=1
}
else {c=2}
}} else{}

I do not know how it should looks with eval, but something like unhighlighted eval("""" eval(""" """) : eval(""" """) """") scares me. Big/red/blinking warning that you can use if-then-else on every page is better than this instruction. It's not correct for usual people - even if them read, it says like 'gscript is integrated in avs+', but most of us do not know what is gscript. Very sad :(

StainlessS
30th July 2019, 16:56
Here script to auto load plugins via an avsi.
Also, has facility to autoload GScript style scripts using GImport() when not AVS+, and just Import when AVS+.

GScripts Directory GIMPORT in Plugins, should have all GScript(""" ... """) style wrappers REMOVED from them.

Allows using same startup/loader on avs 2.6 standard, avs+ x86 and x64.

InitExternalPlugins.avsi

# InitExternalPlugins.avsi

# SetMemoryMax(512) # whatever

# Uses RT_Stats, SysInfo32(or SysInfo64) dlls, and maybe GScript.

RT_DebugF("DBGVIEWCLEAR\n\nAuto load plugins script ENTRY\n",name="InitExternalPlugins: ") # 'DBGVIEWCLEAR' sent to Debugview window clears the window. (thanx Wonkey)

Function ShowAvsInitInfo() {
myName="InitExternalPlugins:ShowAvsInitInfo: "
S=RT_String("\nVersionString = '%s'\n", VersionString)
S=RT_String("%sAvisynth Bitness = %d\n", S,SI_ProcessBitness)
S=RT_String("%sProcessName = '%s'\n", S,SI_ProcessName)
S=RT_String("%sOSVersionString = '%s'\n", S,SI_OSVersionString)
S=RT_String("%sOSVersionNumber = %f\n", S,SI_OSVersionNumber)
S=RT_String("%sCPUName = '%s'\n", S,SI_CPUName)
S=RT_String("%sCores = %02d:%02d (Phy:Log)\n", S,SI_PhysicalCores,SI_LogicalCores)
S=RT_String("%sCPU Extensions = '%s'\n", S,SI_CPUExtensions)
S=RT_String("%sTotal Memory = %dMB\n", S,SI_TotalSystemMemory)
S=RT_String("%sAvail Memory = %dMB'\n", S,SI_AvailableSystemMemory)
S=RT_String("%sScreen Res = %dx%d\n", S,SI_ScreenResX,SI_ScreenResY)
S=RT_String("%sScreen BitPerPixel = %d\n", S,SI_ScreenBitsPerPixel)
S=RT_String("%sTime = '%s'\n", S,Time("%A %d %B %Y %H:%M:%S[%Z]"))
S=RT_String("%sSetMemoryMax = %d\n", S,SetMemoryMax)
RT_DebugF("%s",S,name=myName)
}

Function AvsInit_Load_CPP_Plugin(String fn) {
myName = "InitExternalPlugins:AvsInit_Load_CPP_Plugin: "
Assert(fn != "", +RT_String("%sFn cannot be empty string",myName))
FN = RT_GetFullPathName(fn)
EX = Exist(FN)
Try {
EX ? LoadPlugin(FN) : NOP
EX ? RT_DebugF("%s LOADED OK",RT_FilenameSplit(FN,12).RT_StrPad(32),name=myName) : RT_DebugF("%s NOT FOUND",FN,name=myName)
} catch( msg ) { RT_DebugF("ERROR on '%s'\nSysErr='%s'\n",FN,msg,name=myName) }
}


Function AvsInit_Load_C_Plugin(String fn) {
myName = "InitExternalPlugins:AvsInit_Load_C_Plugin: "
Assert(fn != "", +RT_String("%sFn cannot be empty string",myName))
FN = RT_GetFullPathName(fn)
EX = Exist(FN)
Try {
EX ? Load_Stdcall_Plugin(FN) : NOP
EX ? RT_DebugF("%s LOADED OK",RT_FilenameSplit(FN,12).RT_StrPad(32),name=myName) : RT_DebugF("%s NOT FOUND",FN,name=myName)
} catch( msg ) {
RT_DebugF("ERROR on '%s'\nSysErr='%s'\n",Fn,msg,name=myName)
}
}

Function AvsInit_Import_Avs(String fn) {
myName = "InitExternalPlugins:AvsInit_Import_Avs: "
Assert(fn != "", +RT_String("%sFn cannot be empty string",myName))
FN = RT_GetFullPathName(fn)
EX = Exist(FN)
Try {
EX ? Import(FN) : NOP
EX ? RT_DebugF(" %s IMPORTED OK",RT_FilenameSplit(FN,12).RT_StrPad(32),name=myName) : RT_DebugF("%s NOT FOUND",FN,name=myName)
} catch( msg ) { RT_DebugF("ERROR on '%s'\nSysErr='%s'\n",FN,msg,name=myName) }
}

Function AvsInit_GImport(String dir) { # Import if AVS+, or GImport if NOT AVS+ and GScript present. Import of both *.avs and *.avsi
myName = "InitExternalPlugins:AvsInit_GImport: "
Got=0
IsAvsPlus=(FindStr(VersionString, "AviSynth+")>0 || FindStr(VersionString, " Neo")>0) # EDIT: Added Avisynth Neo
HasGScript=RT_FunctionExist("GScript")
Assert(IsAvsPlus || HasGScript,RT_String("%sMust have Avs+ or GScript",myName))
Assert(dir != "", +RT_String("%sdir cannot be empty string",myName))
Dir = RT_GetFullPathName(Dir)
TEMP=RT_GetSystemEnv("TEMP") + "\~" + RT_LocalTimeString + ".tmp"
nwr = RT_WriteFileList(Dir+"\*.avs|avsi",TEMP)
GS="""
if(nwr > 0) {
for(i=0,nwr-1) {
fn = RT_ReadTxtFromFile(TEMP,Lines=1,Start=i)
fn = RT_TxtGetLine(fn) # Strip NL
try {
if(HasGScript) {
RT_DebugF("GImporting ... %s",fn,name=myName)
GImport(fn)
} Else {
RT_DebugF("Importing ... %s",fn,name=myName)
Import(fn)
}
got=got+1
} catch ( msg ) { RT_DebugF(" *** Catch *** %s",msg,name=myName) }
}
}
"""
(HasGScript) ? GSCript(GS) : Eval(GS)
RT_FileDelete(TEMP)
RT_DebugF(" IMPORTED %d scripts",got,name=myName)
}

##################

ShowAvsInitInfo()

AvsInit_Load_CPP_Plugin (".\DGDecode\DGDecode.DLL") # DGDecode CPP
AvsInit_Load_C_Plugin (".\FFMS2_C\ffms2.dll") # FFMpegSource C Plugin
AvsInit_Import_Avs (".\FFMS2_C\ffms2.avsi") # FFMpegSource C Avsi file with LoadCPlugin line commented OUT.
AvsInit_Load_CPP_Plugin (".\LSMASH_CPP\LSMASHSource.dll") # L-Smash CPP

#AvsInit_Load_CPP_Plugin (".\FFMS2000_CPP\ffms2.dll") # FFMpegSource CPP Plugin
#AvsInit_Import_Avs (".\FFMS2000_CPP\ffms2.avsi") # FFMpegSource CPP Avsi file with LoadCPlugin line commented OUT.

### Below Scripts should NOT have GScript wrappers ie no GScript(""" ... """). Import() scripts for AVS+, and GImport() when GScript installed.

AvsInit_GImport(".\GIMPORT") # GIMPORT foldler inside your Plugins directory.

#AvsInit_GImport("..\..\GIMPORT") # 2 Directories ABOVE plugins, if using Groucho2004 Universal installer, then is in AvisynthRepository smame level as all AVS distro folders.


EDIT: Debug

00000030 18:50:48.623 InitExternalPlugins:
00000031 18:50:48.623 InitExternalPlugins: Auto load plugins script ENTRY
00000032 18:50:48.623 InitExternalPlugins:
00000033 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo:
00000034 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: VersionString = 'AviSynth+ 0.1 (r2900, MT, i386)'
00000035 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Avisynth Bitness = 32
00000036 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: ProcessName = 'C:\NON-INSTALL\VDUB\VDUB2\VirtualDub.exe'
00000037 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: OSVersionString = 'Windows 7 (x64) Service Pack 1.0 (Build 7601)'
00000038 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: OSVersionNumber = 6.100000
00000039 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: CPUName = 'Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz / Yorkfield (Core 2 Quad) 6M'
00000040 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Cores = 04:04 (Phy:Log)
00000041 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: CPU Extensions = 'MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1'
00000042 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Total Memory = 12221MB
00000043 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Avail Memory = 10230MB'
00000044 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Screen Res = 1920x1080
00000045 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Screen BitPerPixel = 32
00000046 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Time = 'Tuesday 30 July 2019 18:50:48[GMT Daylight Time]'
00000047 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: SetMemoryMax = 1024
00000048 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo:
00000049 18:50:48.623 InitExternalPlugins:AvsInit_Load_CPP_Plugin: DGDecode.DLL LOADED OK
00000050 18:50:48.623 InitExternalPlugins:AvsInit_Load_C_Plugin: ffms2.dll LOADED OK
00000051 18:50:48.623 InitExternalPlugins:AvsInit_Import_Avs: ffms2.avsi IMPORTED OK
00000052 18:50:48.623 InitExternalPlugins:AvsInit_Load_CPP_Plugin: LSMASHSource.dll LOADED OK
00000053 18:50:48.639 InitExternalPlugins:AvsInit_GImport: Importing ... C:\VideoTools\AvisynthRepository\AVSPLUS_x86\plugins\GIMPORT\MIFO_Library.avsi
00000054 18:50:48.639 InitExternalPlugins:AvsInit_GImport: IMPORTED 1 scripts


OOps, line in red changed
EDIT: Added AviSynth Neo as avs+

StainlessS
30th July 2019, 18:54
Added line, allows using SAME folder of gscript scripts for ALL distros where using Groucho2004 Universal installer.
[although is currently commented out and using the one in current plugins]

AvsInit_GImport("..\..\GIMPORT") # 2 Directories ABOVE plugins, if using Groucho2004 Universal installer, then is in AvisynthRepository same level as all AVS distro folders.


Post 44, Added SetMemoryMax line to Avisynth info display as in

00000030 18:50:48.623 InitExternalPlugins:
00000031 18:50:48.623 InitExternalPlugins: Auto load plugins script ENTRY
00000032 18:50:48.623 InitExternalPlugins:
00000033 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo:
00000034 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: VersionString = 'AviSynth+ 0.1 (r2900, MT, i386)'
00000035 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Avisynth Bitness = 32
00000036 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: ProcessName = 'C:\NON-INSTALL\VDUB\VDUB2\VirtualDub.exe'
00000037 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: OSVersionString = 'Windows 7 (x64) Service Pack 1.0 (Build 7601)'
00000038 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: OSVersionNumber = 6.100000
00000039 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: CPUName = 'Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz / Yorkfield (Core 2 Quad) 6M'
00000040 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Cores = 04:04 (Phy:Log)
00000041 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: CPU Extensions = 'MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1'
00000042 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Total Memory = 12221MB
00000043 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Avail Memory = 10230MB'
00000044 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Screen Res = 1920x1080
00000045 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Screen BitPerPixel = 32
00000046 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: Time = 'Tuesday 30 July 2019 18:50:48[GMT Daylight Time]'
00000047 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo: SetMemoryMax = 1024
00000048 18:50:48.623 InitExternalPlugins:ShowAvsInitInfo:
00000049 18:50:48.623 InitExternalPlugins:AvsInit_Load_CPP_Plugin: DGDecode.DLL LOADED OK
00000050 18:50:48.623 InitExternalPlugins:AvsInit_Load_C_Plugin: ffms2.dll LOADED OK
00000051 18:50:48.623 InitExternalPlugins:AvsInit_Import_Avs: ffms2.avsi IMPORTED OK
00000052 18:50:48.623 InitExternalPlugins:AvsInit_Load_CPP_Plugin: LSMASHSource.dll LOADED OK
00000053 18:50:48.639 InitExternalPlugins:AvsInit_GImport: Importing ... C:\VideoTools\AvisynthRepository\AVSPLUS_x86\plugins\GIMPORT\MIFO_Library.avsi
00000054 18:50:48.639 InitExternalPlugins:AvsInit_GImport: IMPORTED 1 scripts

StainlessS
30th July 2019, 20:13
Oops, line in post #44 in red changed.
Was

Assert(IsAvsPlus || HasGScript)

now

Assert(IsAvsPlus || HasGScript,RT_String("%sMust have Avs+ or GScript",myName))


Kept getting my scripts mixed up, thats what happens when got a slightly different one in each of the Avisynth Universal Installer Plugins dir.

ChaosKing
30th July 2019, 20:15
Oops, line in post #44 in red changed.
Kept getting my scripts mixed up, thats what happens when got a slightly different one in each of the Avisynth Universal Installer Plugins dir.

That is why I use one plugins dir for plugins and one only for scripts :D

PluginDir2_5 (HKLM, x86): D:\AvisynthRepository\AVSPLUS_x86\plugins
PluginDir+ (HKLM, x86): D:\AvisynthRepository\SCRIPTS

StainlessS
30th July 2019, 20:26
Clever cloggs :)

Now can solve all of that nonsense with GScript/Avs+, can remove all GScript wrappers from scripts, avs v2.58, 2.60, 2.61, avs+ x86 and x64, Neo x86, x64.

StainlessS
9th May 2020, 14:23
GSCript("")

Above causes Access Violation, both in original v1.1, and Groucho2004 recompile for x86 and x64.

EDIT: Actually, causes AV in current Avs+, however original v1.1 does NOT cause Access Violation under Avs 2.58. [v1.1 OK under v2.60 too]

Groucho2004
9th May 2020, 15:01
GSCript("")

Above causes Access Violation, both in original v1.1, and Groucho2004 recompile for x86 and x64.

EDIT: Actually, causes AV in current Avs+, however original v1.1 does NOT cause Access Violation under Avs 2.58. [v1.1 OK under v2.60 too]For me, VDub2 throws this:
https://i.postimg.cc/TY5yD5tk/Image1.png

Edit - AVSMeter doesn't seem to be bothered at all. It just runs the script. This is the script I used:
resx = 1000
resy = 1000
colorbars(width = resx, height = resy, pixel_type = "yv12").killaudio().assumefps(25, 1).trim(0, 99999).loop(1000)
GScript("")
return last