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.

Domains: forum.doom9.org / forum.doom9.net / forum.doom9.se

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 4th November 2011, 09:20   #21  |  Link
redfordxx
Registered User
 
Join Date: Jan 2005
Location: Praha (not that one in Texas)
Posts: 863
OK, i see:
Few options how to deal with this issue depending how much rounding errors bother you...
Let's clear
Code:
#drawsrtm5=lutexpression resulting in mask (0,255)
#drawsrtm6=lutexpression resulting in mask (0,256)
#drawsrtm16=lutexpression resulting in 16bit mask (0,65535)
#if no better idea
#drawsrtm16=drawsrtm5 256 * drawsrtm5 128 - 2 *
#drawsrtm6=drawsrtm16 256 /
How about few variants of this
Code:
picture=mt_lutspa(c,drawstry+ " 256 "+drawstrm6+" - * 128 + 256 /")
mask=mt_lutspa(c,drawstrm5)
mask2=mt_lutspa(c,drawstrm5+" 128 - 2 *")
result1=mt_lutxy(c,mask,"x y * 128 + 256 /") #i don't know any faster multiplication algorithm axcept my modification of AverageM
result2=mt_lutxy(c,mask2,"x y * 128 + 256 /")
Average(picture, 1.0, result1, 1.0, result2, 1/256)
Which should be ok for your opacity issue but not so good for rounding errors
redfordxx is offline   Reply With Quote
Old 4th November 2011, 09:37   #22  |  Link
redfordxx
Registered User
 
Join Date: Jan 2005
Location: Praha (not that one in Texas)
Posts: 863
Unless you want to go to higher bitdepth like dither...
...this should be fast and precise
Code:
picture=mt_lutspa(c,drawstry)
#4 masks (I still believe, lutspa runs only once per clip, so this should be no efficiency issue, otherwise and in case of real masks we might need binarize...)
m_up=mt_lutspa(c,drawstrm6+" 128 -")
m_dn=mt_lutspa(c,drawstrm6+" 128 max")
m_n_up=mt_lutspa(c,"256 "+drawstrm6+" - 128 -")
m_n_dn=mt_lutspa(c,"256 "+drawstrm6+" - 128 max")

AverageM(c, m_up, c, m_dn,   picture, m_n_up, picture, m_n_dn)
iirc AverageM does in this case
(c*m_up+c*m_dn+picture*m_n_up+picture*m_n_dn+128)/256
which should be quite fast. Definitely faster than your script.
Moreover, you can use (0;256) masks this way...
But, it does all color planes always...

Average thread

Last edited by redfordxx; 4th November 2011 at 09:40.
redfordxx is offline   Reply With Quote
Old 8th November 2011, 15:30   #23  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Excuse me for being the devil's advocate, but why exactly have you written 100 lines of masktools voodoo to do something that is trivially accomplished with blankclip, crop, stack(vertical|horizontal) and overlay? There are also several other existing ways to do this using various plugins (textsub and assrender allow you to render arbitrary vector drawings with subpixel precision, for example), most of which render roughly an order of magnitude faster.

I understanding coding for the sake of coding and being fascinated with one's own cleverness, but this does seem a bit excessive.

Last edited by TheFluff; 8th November 2011 at 15:33.
TheFluff is offline   Reply With Quote
Old 8th November 2011, 17:15   #24  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
I looked at textsub and assrender, and see no way that they can draw arbitrary shapes. They both take a special text file. About the only way to draw anything might be with spaces, and even then it would be very difficult to specify they're exact coordinates. Finally, they don't accept any kind of yuv colors.

We both tried blank/crop/stack, it's slow and quite awkward (not trivial), but the killer is overlay is not precise enough. It converts everything to it's internal format, mixes, then converts back again, making it slow and imprecise.

Both crop and overlay have bugs:
http://avisynth.org/mediawiki/Known_Issues

By all means, if you can think of a way to draw a few types of shapes in YUV directly, quickly and accurately, please let me know! Most people seem to want only masks of 255 in certain shapes, but I want to make specifically test patterns (not just colorbars).

Last edited by jmac698; 8th November 2011 at 17:18.
jmac698 is offline   Reply With Quote
Old 8th November 2011, 19:48   #25  |  Link
AzraelNewtype
Registered User
 
AzraelNewtype's Avatar
 
Join Date: Oct 2007
Posts: 135
Quote:
Originally Posted by jmac698 View Post
I looked at textsub and assrender, and see no way that they can draw arbitrary shapes. They both take a special text file. About the only way to draw anything might be with spaces, and even then it would be very difficult to specify they're exact coordinates.
So what you're saying here is, you looked at textsub and assrender as plugins, but did not spend any time whatsoever looking at the ass format that they, er... render before coming to this conclusion? Because you're completely wrong, and TheFluff is absolutely correct.
AzraelNewtype is offline   Reply With Quote
Old 8th November 2011, 20:20   #26  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
No, I did look at the formats. Here's a link: http://matroska.org/technical/specs/subtitles/ssa.html
I also read both manuals. No mention of drawing shapes. You don't have to use such wording; if there's no obvious mention of how to do this, it's understandable that I can't find it. I looked again and still can't find it.

I didn't explain a further point of using text files; this doesn't help me draw shapes programaticaly (sp?). As I mentioned I'm making test images; some of them I'd like to animate as well.
jmac698 is offline   Reply With Quote
Old 8th November 2011, 22:02   #27  |  Link
redfordxx
Registered User
 
Join Date: Jan 2005
Location: Praha (not that one in Texas)
Posts: 863
I have one more thing for you.
Whenever you use lutspa, put .trim(1,1).Loop(c.framecount,0,0) after it. It will boost your speed extremely.
redfordxx is offline   Reply With Quote
Old 8th November 2011, 22:09   #28  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,442
Quote:
Originally Posted by jmac698 View Post
We both tried blank/crop/stack, it's slow and quite awkward (not trivial), but the killer is overlay is not precise enough. It converts everything to it's internal format, mixes, then converts back again, making it slow and imprecise.

Both crop and overlay have bugs:
http://avisynth.org/mediawiki/Known_Issues
These bugs only affect RGB.
Also, conversion in Overlay doesn't change luma of YUV inputs, though yes, YUY2 and YV12 chroma will be internally upsampled to 4:4:4.

But in any case, your function is far more complex than it need be. There is no need to use (the extremely slow loading) mt_lutxyz, or to have a special case opacity=256. You can use opacity=255 to mean full opacity, and implement the function as follows:
1. Create the (luma and chroma) mask using mt_lutspa, setting pixels to 'opacity' in the drawing region and zero elsewhere.
2. Use mt_lutxy to process the input clip and mask to set
output = (mask*color + (255-mask)*input)/255
where color is the specified drawing color (for each of y, u, v).
That's it!
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 8th November 2011, 22:38   #29  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Quote:
Originally Posted by jmac698 View Post
No, I did look at the formats. Here's a link: http://matroska.org/technical/specs/subtitles/ssa.html
I also read both manuals. No mention of drawing shapes. You don't have to use such wording; if there's no obvious mention of how to do this, it's understandable that I can't find it. I looked again and still can't find it.
You're looking at a very brief summary of an incomplete document that not only is well over a decade old, it was also a very inaccurate description of what actually was implemented in subtitle renderers even when it was brand new.

The least incomplete documentation of the ASS format that I am aware of is available in the manual for the Aegisub subtitle editor. There are several modified versions of VSFilter (textsub) floating around that add their own custom extensions, but the stuff that the Aegisub manual covers is supported in all known modern versions. For the vector drawing stuff, take a look at the bottom of the page linked above, under the heading "Drawing commands".

That said, even the ancient document I was referring to above, which the Matroska page you mention links to, mentions the drawing tags. The syntax is still the same despite the format being old enough to drive a car in some jurisdictions.

A feature of the ASS format's vector drawing mode that is worth mentioning is that since it's actually a real vector drawing system, it uses its own internal coordinate system that is completely unrelated to the video pixel grid, which means that any shapes you draw with it can be rendered at any video resolution without modification of the drawing commands. It also means you can actually render with subpixel precision if you so desire.

Quote:
Originally Posted by jmac698 View Post
I didn't explain a further point of using text files; this doesn't help me draw shapes programaticaly (sp?). As I mentioned I'm making test images; some of them I'd like to animate as well.
If you want to generate animated shapes programatically, Avisynth script seems like an exceptionally bad choice of programming language. Even if you use grunt and/or gscript it still seems like an incredibly annoying task. ASS subtitle files are plain text; it's rather trivial to generate them programatically in almost any language. There is also a multitude of existing tools for generating such files in various ways already. Aegisub, for example, comes both with a vector drawing tool that outputs ASS drawing commands, as well as with a complete scripting system intended for generating and manipulating ASS subtitle files (and much like with Avisynth scripting, there is a rather big library of user-contributed scripts written for this scripting system).

Last edited by TheFluff; 8th November 2011 at 23:17.
TheFluff is offline   Reply With Quote
Old 9th November 2011, 09:45   #30  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,442
Quote:
Originally Posted by Gavino View Post
You can use opacity=255 to mean full opacity, and implement the function as follows:
1. Create the (luma and chroma) mask using mt_lutspa, setting pixels to 'opacity' in the drawing region and zero elsewhere.
2. Use mt_lutxy to process the input clip and mask to set
output = (mask*color + (255-mask)*input)/255
where color is the specified drawing color (for each of y, u, v).
Specifically, what I meant was change the default opacity to 255 and change this code:
Code:
    drawstry=buildrectexp(xl, yl, xh, yh, y, 16, filled)
    drawstru=buildrectexp(xl2, yl2, xh2, yh2, u, 128, filled)
    drawstrv=buildrectexp(xl2, yl2, xh2, yh2, v, 128, filled)
    drawstrm=buildrectexp(xl, yl, xh, yh, opacity, 0, filled)
    drawstrmuv=buildrectexp(xl2, yl2, xh2, yh2, opacity, 0, filled)
    mergeit(c, drawstry, drawstru, drawstrv, drawstrm, drawstrmuv, opacity)
}

function mergeit(clip c, string drawstry, string drawstru, string drawstrv, string drawstrm, string drawstrmuv, int opacity){
    mt_lutspa(c, mode="absolute", yexpr=drawstry, uexpr=drawstru, vexpr=drawstrv, chroma="process")
    mask=mt_lutspa(c, mode="absolute", yexpr=drawstrm, uexpr=drawstrmuv, vexpr=drawstrmuv, chroma="process")
    opacity==256?mt_lutxyz(c, mask, last, expr="y 255 = z x ?", chroma="process"):mt_merge(c, last, mask, luma=true, chroma="process")
}
to this:
Code:
    drawstrm=buildrectexp(xl, yl, xh, yh, opacity, 0, filled)
    drawstrmuv=buildrectexp(xl2, yl2, xh2, yh2, opacity, 0, filled)
    mask=mt_lutspa(c, mode="absolute", yexpr=drawstrm, uexpr=drawstrmuv, vexpr=drawstrmuv, chroma="process")
    mt_lutxy(c, mask, yexpr=drawstr(y), uexpr=drawstr(u), vexpr=drawstr(v), chroma="process")
}

function drawstr(int clr) {
    return string(clr)+ " y * 255 y - x * + 255 /"
}
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 9th November 2011, 17:48   #31  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
@Dogway,

Quote:
sometimes I may want 255 so I can use it as a mask. For the same reason it would be good if you could also add a background color, that is empty (bypass to clip) or some color like black for masks.
I added this feature for you, try createrect(x1,y1, x2,y2) it will do what you want, and it's fast.

@Gavino
Thanks, I used some of your suggestions, and still have a full range for opacity.

@Fluff
I found the documentation for drawing, but it only does lines and splines, so I can't draw a circle. Also it only specifies colors in RGB, so it's impossible to create certain YUV colors. And now my script is almost 170 lines, and that's because Avisynth is missing so many features.

That reminds me of the day I tried Gimp. I wanted to draw a circle, but couldn't figure out how. Then I read a doc which said "Gimp can't draw circles, but that's not what it's for...". I gave up on Gimp on that day.

@any
I'd like to make this deepcolor compatible, but I discovered yet another bug in 2.6a3 which prevents me.

Last edited by jmac698; 9th November 2011 at 17:56.
jmac698 is offline   Reply With Quote
Old 9th November 2011, 19:05   #32  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,442
Quote:
Originally Posted by jmac698 View Post
@Gavino
Thanks, I used some of your suggestions, and still have a full range for opacity.
I don't see the point of having 0-256 instead of 0-255.
The latter seems more natural to me and the former introduces an unnecessary special case into the code for no appreciable gain. But then it's your function, so please yourself.

BTW Your 'higher' and 'lower' functions can be replaced by 'min' and 'max' (since v2.58).

Quote:
@Dogway,
I added this feature for you, try createrect(x1,y1, x2,y2) it will do what you want, and it's fast.
For mask creation, you normally don't care about the chroma.
Perhaps you want a (faster) option that just sets the luma.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 9th November 2011, 19:28   #33  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
Updated. Thanks for the suggestion.

I have to use opacity(0,256) solely for the important case of 128, which gives an exact average. I could even add another special case for that and use averagem which is apparently faster. Oh, how horrid would that be
jmac698 is offline   Reply With Quote
Old 9th November 2011, 19:38   #34  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
Here's my function which will break if floats ever change in avisynth:
Code:
x1=getword1(65536*256+256*1+3,0)
x2=getword2(65536*256+256*1+3,0)
messageclip("Result of getword1="+string(x1)+" result of getword2="+string(x2))

function getword1(int n, int p, int "size"){
    #Get word p of size size from n, limited to p=(0,2)
    #Warning:  due to the implementation in avisynth, p=2 and size=2 gives wrong answers
    size=default(size, 1)
    f=pow(2,8*size*2)
    p2=floor(n/f)
    n=n-p2*f#This subtraction won't work in some cases when n is int and f is float
    f=pow(2,8*size*1)
    p1=floor(n/f)
    n=n-p1*f
    p0=n
    int(p==0?p0:p==1?p1:p2)
}

function getword2(int n, int p, int "size"){
    #Get word p of size size from n, limited to p=(0,2)
    #Warning:  only works with an assumed implementation in avisynth
    size=default(size, 1)
    f=int(pow(2,8*size*2))
    p2=n/f
    n=n-p2*f
    f=int(pow(2,8*size*1))
    p1=n/f
    n=n-p1*f
    p0=n
    int(p==0?p0:p==1?p1:p2)
}
jmac698 is offline   Reply With Quote
Old 9th November 2011, 19:50   #35  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,442
Quote:
Originally Posted by jmac698 View Post
Here's my function which will break if floats ever change in avisynth:
Surely the right (and implementation independent) way to do this is by successive integer division (equivalent to shifting right)?
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 9th November 2011, 19:56   #36  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Quote:
Originally Posted by jmac698 View Post
@Fluff
I found the documentation for drawing, but it only does lines and splines, so I can't draw a circle. Also it only specifies colors in RGB, so it's impossible to create certain YUV colors. And now my script is almost 170 lines, and that's because Avisynth is missing so many features.

That reminds me of the day I tried Gimp. I wanted to draw a circle, but couldn't figure out how. Then I read a doc which said "Gimp can't draw circles, but that's not what it's for...". I gave up on Gimp on that day.
Your script only draws rectangles, so I have absolutely no idea why you'd cite not being able to draw circles as a drawback of ASS. It's not even a very significant drawback, since you can get within epsilon of a perfect circle with little effort.

I don't see how "certain YUV colors" can be impossible to create either (the YUV<->RGB conversion formula is not exactly rocket science), and I most certainly don't see what the GIMP team's design decision to not make it a vector art tool has to do with all of this.
TheFluff is offline   Reply With Quote
Old 9th November 2011, 20:03   #37  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
I need to do my computations in the format (float or int) which has enough precision for them; in my case I want to extract words from a packed deepcolor value, which takes 3*16=48 bits. So it turns out I can't do this anyway. It's bad enough that Avisynth doesn't handle deepcolor, but it's a real pain when I can't even store a single color properly. I need much higher precision.

Another problem is trying to pass around multiple values in the language itself; it just can't be done. I guess my problem is the single return value isn't big enough to even pack my answer into.
jmac698 is offline   Reply With Quote
Old 9th November 2011, 20:12   #38  |  Link
amtm
Guest
 
Posts: n/a
The format of "float" will not change. "Float" will always be single-precision.
  Reply With Quote
Old 9th November 2011, 20:25   #39  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,100
Quote:
Originally Posted by jmac698 View Post
I need to do my computations in the format (float or int) which has enough precision for them; in my case I want to extract words from a packed deepcolor value, which takes 3*16=48 bits. So it turns out I can't do this anyway. It's bad enough that Avisynth doesn't handle deepcolor, but it's a real pain when I can't even store a single color properly. I need much higher precision.

Another problem is trying to pass around multiple values in the language itself; it just can't be done. I guess my problem is the single return value isn't big enough to even pack my answer into.
I'm sort of astounded that despite repeated proddings you still haven't seemed to realize that perhaps Avisynth scripting and masktools aren't the right tools for this job. What you want to do isn't complicated in the slightest, and I am absolutely astounded that you keep hacking on this bizarre mess rather than trying to find out a saner way to do it.

You could probably write a standalone C program that does what your script does on uncompressed video files in less lines of code than your entire script, even if you included file I/O operations.
TheFluff is offline   Reply With Quote
Old 9th November 2011, 20:29   #40  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,869
@Fluff
Quote:
\1c&H<bb><gg><rr>&
This seems to set the primary fill color which is used by the shapes in draw mode. You'll note it only accepts 8 bits.

Two problems:
I'm afraid you don't understand the finer points of colorspaces. It would take negative rgb components to cover all the normal yuv colors. Here's an example calculation for -Q in Rec601:
y = 16, cb = 158, cr = 95
for rgb [16,235]: r = 219*(-0.2067)+16 = -29, g = 219*0.0588+16 = 29, b = 219*0.2394+16 = 68
From http://avisynth.org/mediawiki/ColorBars_theory
which is actually from a discussion I started years ago, resulting in proper colorbars colors in avisynth 2.56:
http://forum.doom9.org/showthread.php?t=107682&page=2
Quote:
Originally Posted by IanB
Yes, not all YUV (or YIQ) values have corresponding RGB values. This is not news.
2. I don't believe 8 bits is enough to cover even the permissible YUV colors, also in 8 bits.
jmac698 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 05:51.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.