PDA

View Full Version : Trim and Empty Clip


tacman1123
16th October 2008, 20:37
I'm looking at the Replace() function that someone wrote, and I think there's a problem if you're trying to replace the very first part of a clip. Here's the function (from somewhere in this forum, or maybe in the wiki):


function Replace (clip old, clip inclip, int frame, int numframes)
{
numframes = ((numframes == 0) || (numframes > inclip.framecount)) ? inclip.framecount : numframes
return old.Trim(0, frame - 1) + inclip.Trim(0, numframes) + old.Trim(frame + numframes, 0)
}


If I'm trying to replace the first x frames, I'd call

c.Replace(b, 0, 10)

However, that would call old.Trim(0, -1), which returns the first frame (according to the documentation on the Trim() page.

Part of the problem is that Trim() is overloaded -- if the second parameter is negative, then it means "framecount", so get 1 frame starting a frame zero. But what I want is zero frames.

Because Avisynth doesn't have if statements, something like this can be confusing for all but expert script writers. But hopefully someone will point me in the right direction!

Tac

PS Yes, I realize that Replace starting with zero could be rewritten as an align without ever calling replace, but I still would like to know how to do it, so that if it's called programmatically the function works as expected.

neuron2
16th October 2008, 20:54
function Replace (clip old, clip inclip, int frame, int numframes)
{
numframes = ((numframes == 0) || (numframes > inclip.framecount)) ? inclip.framecount : numframes
return (frame > 0) ? old.Trim(0, frame - 1) + inclip.Trim(0, numframes) + old.Trim(frame + numframes, 0) : \
inclip.Trim(0, numframes) + old.Trim(frame + numframes, 0)
}

Gavino
16th October 2008, 20:57
tac, I don't know where you got that Replace function from, but it's rubbish. Not only does it fail to handle frame=0 correctly, it adds one frame more than it should.

For any question about function writing, your first port of call should be stickboy's functions (http://avisynth.org/stickboy/). There you will find JDL_ReplaceRange and lots of other good stuff as well.

If you want to see how to write functions well, spend a little while studying the code of all these functions.

Gavino
16th October 2008, 21:20
function Replace (clip old, clip inclip, int frame, int numframes)
{
numframes = ((numframes == 0) || (numframes > inclip.framecount)) ? inclip.framecount : numframes
return (frame > 0) ? old.Trim(0, frame - 1) + inclip.Trim(0, numframes) + old.Trim(frame + numframes, 0) : \
inclip.Trim(0, numframes) + old.Trim(frame + numframes, 0)
}

I guess you just copied tac's version without looking too closely, but this also fails when frame=1 (a common mistake with functions like this). Here's a better one.

function Replace (clip old, clip inclip, int frame, int numframes)
{
numframes = ((numframes == 0) || (numframes > inclip.framecount)) ? inclip.framecount : numframes
return (frame > 0) ? old.Trim(0, -frame) + inclip.Trim(0, -numframes) + old.Trim(frame + numframes, 0) : \
inclip.Trim(0, -numframes) + old.Trim(frame + numframes, 0)
}

Even then it doesn't cater for the replacement clip reaching the end of the old clip.

stickboy
16th October 2008, 23:50
Here's a better one.

function Replace (clip old, clip inclip, int frame, int numframes)
{
numframes = ((numframes == 0) || (numframes > inclip.framecount)) ? inclip.framecount : numframes
return (frame > 0) ? old.Trim(0, -frame) + inclip.Trim(0, -numframes) + old.Trim(frame + numframes, 0) : \
inclip.Trim(0, -numframes) + old.Trim(frame + numframes, 0)
}

Even then it doesn't cater for the replacement clip reaching the end of the old clip.Does that work for Replace(old, inclip, 0, 0) ? I don't remember offhand; does Trim(0, 0) return the entire clip?

It's much, much simpler to avoid trying to use Trim in functions like this. Use my Trim2/Trim3 functions instead. (See Caveats of using Trim in functions (http://forum.doom9.org/showthread.php?s=&threadid=58358).)

tacman1123
16th October 2008, 23:52
You're absolutely right, the first place to go is JDL's routines. The solution isn't simple, but he's provided it in JDL_ReplaceRange (which calls Trim2, which calls NullClip, both things I couldn't figure out how to handle in my original post).

I'd love to see more references to routines like this in the wiki, rather than just in the forums. Unfortunately, the capcha routine in the wiki is broken more often than not. My browser has been spinning for about 4 minutes trying to bring up an image, which is so cleverly convoluted that in the few times it's come up, I often don't type it correctly because I can't read it. I can't be the only one having this problem, and so I'm frustrated, not only because I can't add to the wiki, but because the wiki generally gets better with more contributions, and I'm sure I'm not the only one that's had something worthwhile to add but given up because the technology was in the way.

Anyway, I'm both using the JDL routines now and learning a lot from them!

Thx,

Tac

tacman1123
17th October 2008, 00:38
@Stickyboy: FYI, there's a typo on line 490 of jdl-util.avsi, says "ruturn", should be "return". Do you plan to upgrade the scripts for 2.5.8? Is there any particular value to doing so?

Gavino
17th October 2008, 00:44
Does that work for Replace(old, inclip, 0, 0) ? I don't remember offhand; does Trim(0, 0) return the entire clip?
Yes, it does.
It's much, much simpler to avoid trying to use Trim in functions like this. Use my Trim2/Trim3 functions instead. (See Caveats of using Trim in functions (http://forum.doom9.org/showthread.php?s=&threadid=58358).)
Agreed. This should be required reading for all function writers.

stickboy
17th October 2008, 02:01
@Stickyboy: FYI, there's a typo on line 490 of jdl-util.avsi, says "ruturn", should be "return". Do you plan to upgrade the scripts for 2.5.8? Is there any particular value to doing so?Thanks for finding that. It should be fixed now.

I'm planning on pushing all the deprecated functions into a separate jdl-glue.avsi file, but I haven't gotten around to it yet. AviSynth development has slowed down, so there's a lot less need for keeping those backward-compatibility functions around.