First function is another function that works like applyrange. Now, I know that there have been made various in the past, including Phantasmagoriat's range, which I had been using up until now.
However, for 3 reasons I decided to write my own:
1) Phan's range does all the fade etc things, which are cool advanced features if you need them, but end up using some unnecessary memory if you don't.
2) The fixes it did for the checks weren't completely correct. It would change the values with all (which is the framecount) instead of all-1 (which is the actual number of the last frame in the stream, since the first frame is frame 0).
3) It didn't allow me to use -num_frames from trim if I wanted to, so it was completely impossible to actually filter only on frame 0 by just specifying startframe and endframe, which is how I can most easily automate it within YATTA's Custom Lists.
While if it was only for reason 2, I could have just easily updated his range function, reasons 1 and 3 lead me to the decision to just redo it from the beginning. The former, because I'd have to trash some neat things it does, which are helpful from time to time, but not in my daily usage. The latter, because I didn't have the effort to actually look into the code enough to see what I had to change without screwing up anything.
So well, here's the code:
Code: Select all
#strange v1.3 by mirkosp
#Yet Another function similar to ApplyRange in purpose that works somewhat differently.
#Start and end work exactly like first_frame and last_frame work with trim(), for the
#sake of consistency, which means that you can use end as if it was -num_frames too.
#ofps parameter tells whether to keep the original fps (true) or not (false).
#For reference: http://avisynth.org/mediawiki/Trim
function strange (clip c, int "start", int "end", clip "edit", bool "ofps") {
#This function only makes sense with filters that return clips to begin with, so no
#point in bothering with strings. It's both easier and better.
start = default(start,0)
end = default(end,0)
edit = default(edit,blankclip(c,length=c.framecount()))#everybody loves blankclip
amount = c.framecount()
ofps = default(ofps,false)
#Brainfarts check ahead.
start = (start < 0) ? 0 : start
end = (-end > amount-start) ? 0 : end
start = (start > amount) ? amount-1 : start
end = (end > amount-1) ? 0 : end
#Match framerate in case user's custom filtering would change it
c = !ofps ? c.assumefps(edit) : c
edit = ofps ? edit.assumefps(c) : edit
#I'm not a good programmer, so I'm not sure if this is slower than it could be.
(start == 0) ? ((end == 0) || (end == amount-1)) ? edit :\
(end < 0) ? edit.trim(0,end)+c.trim(start-end,0) :\
edit.trim(0,end)+c.trim(end+1,0) :\
(start == 1) ? ((end == 0) || (end == amount-1)) ? c.trim(0,-1)+edit.trim(start,0) :\
(end < 0) ? c.trim(0,-1)+edit.trim(start,end)+c.trim(start-end,0) :\
c.trim(0,-1)+edit.trim(start,end)+c.trim(end+1,0) :\
((end == 0) || (end == amount-1)) ? c.trim(0,start-1)+edit.trim(start,0) :\
(end < 0) ? c.trim(0,start-1)+edit.trim(start,end)+c.trim(start-end,0) :\
c.trim(0,start-1)+edit.trim(start,end)+c.trim(end+1,0)
}
Code: Select all
strange(0,-1,subtitle("Hi I'm a string on just the first frame"))
I tried to check all odd cases that could throw trim off, and they worked fine. I might have still missed something, so do report bugs. The code should be legible and easy enough to understand, too.
Still, while you can use it on single filters, and that's fine if you only have a few instances in the script, if you need to use, say, nnedi3 on a couple hundred frames in different points, instead of having 200 strange(x,y,nnedi3), I'd suggest you to save a clip at the beginning and then calling that, ie:
Code: Select all
nnedi3clip = nnedi3()
strange(x,y,nnedi3clip)
With strange out of the way, the second filter I had the need to make is one that I called fadefix since I'm bad with names. I'm positive other people made something like this too, but this one I haven't been able to find anywhere, so it might be more useful than strange:
Code: Select all
#fadefix v1.1 by mirkosp
#changes a frame with an overlay of the prev and next frames
#weight of the next frame is controlled with fad
#omode is the mode parameter of overlay
function fadefix (clip c, float "fad", int "prev", int "next", string "omode") {
fad = default(fad, 0.5)
prev = default(prev, 1)
next = default(next, 1)
omode = default(omode, "Blend")
assert( (fad > 0.0 && fad < 1.0) , "fad must have a value between 0.0 and 1.0." )
fads = string(fad)
prevs = string(prev)
nexts = string(next)
c
scriptclip("""overlay(last.trim(current_frame-"""+prevs+""",current_frame-"""+prevs+"""),last.trim(current_frame+"""+nexts+""",current_frame+"""+nexts+"""),opacity = float("""+fads+"""),mode = """+CHR(34)+omode+CHR(34)+""" )""")
return last
}
Ok, now, let's explain why this filter has a reason to exist.
Since MPEG-2 is very bad with fades and high luma changes in general, it can often show fucked up frames during fades. While in some cases one could just keep a single field, in others, if one does not feel like photoshopping, nuke would be the only option. I made this filter because in certain occasions, without the need to do heavy photoshopping, one could restore such bad frames without nuking the frame, or at least not in their entirety, which ends up being a better solution for quality and detail.
This filter is meant to be used in tandem with an applyrange-like filter (such as strange). To further explain how it works, I'll show an example.
Let's say that your MPEG-2 animu has fade, and a frame during that fade looks really bad. Now, let's say that this frame is frame 9001, and that by overlaying frames 8999 and 9003 with the same weight, you could restore it. Here's how it would look in avisynth with the former filters:
Code: Select all
strange(9001,9001,fadefix(0.5,2,2))
But as for the values of prev and next, it might not be entirely immediate. Since I can't come up with an explanation in words, I'll show it visually:
Code: Select all
prev next
8998 8999 9000 9001 9002 9003 9004
3 2 1 0 1 2 3
An advanced use of fadefix combined with masks in lieu of just nuking a frame could have unexpectedly pleasant results without too much effort.
Using previous numbers, let's say that we have frame 9001, 8999 and 9003. As you can see, the object at the top rotates, so we can't just overlay, but aside from that, the image is static, so with a simple mask to nuke only where we can't overlay, we can do:
Code: Select all
strange(9001,9001,mt_merge(nlmeanscl(h=6,plane=4),fadefix(0.6,2,2,"lighten"),imagesource("maskdelframe9001.png").converttoyv12.mt_binarize.blurmod(3),true))
Since they don't seem to be buggy enough to be troublesome while being not unuseful enough to not be worth sharing, I decided that I should post them here. Try and see if you can get a use for them or something.