Log in

View Full Version : Help with autoresize function


turbojet
21st July 2010, 08:42
I use this function which works fine when PAR is 1:1

function AutoResizeMod8(clip c,int newwidth,string resizer) {
nhtemp=floor(eval(string(c.height)+". * "+string(newwidth)+". / "+string(c.width)+"."))
nh=(nhtemp+4)/8*8
return eval(resizer+"Resize(c,"+string(newwidth)+","+string(nh)+")") }

and use it in scripts as: autocrop(0).AutoResizeMod8(640,"Lanczos")

However it doesn't work correctly with non-1:1 PAR sources. Any idea on what to add/change to get it resizing correctly to 1:1 from 4:3/16:9 480i/p and 576i/p sources?

Robert Martens
24th July 2010, 01:01
I've been dealing with this subject recently myself, I think I might be able to help. I'd add a new parameter to let you specify the input pixel aspect:


function AutoResizeMod8(clip c,int newwidth,string resizer,float PARin) {

nhtemp = newwidth / ((c.Width() * PARin) / c.Height())
nh = Round(nhtemp / 8.0) * 8

Eval(resizer + "Resize(c,newwidth,nh)") }

You'd then use 10.0/11.0 for NTSC DV, 59.0/54.0 for PAL DV, or 40.0/33.0 and 118.0/81.0 for the wide version of each, respectively (I got the values I use in my own script from VirtualDub, and they seem to work well, but adding PARin lets you use whatever numbers you like).

Multiply the pixel aspect by the input's actual width to get the square pixel equivalent, then divide that by the input's height to get the input frame's display aspect ratio. Divide the requested newwidth by that result, and you have your baseline new height.

To make it mod 8, I think--someone correct me if I'm wrong here--you need to add the Round(), as I did, after dividing by your desired multiple. Otherwise the floating point result of that division just gets multiplied by the mod value and you end up right back where you started.

Along with that addition, I hope you don't mind I took the liberty of cleaning up those Eval calls; nothing personal, just a little tidying up.

You might also consider giving yourself a way to enter the desired new height, too, and generate the width from that. Similar process, but once you get the display aspect of the input frame you'd multiply it by the desired output height, as opposed to dividing the desired output width by said DAR.

I don't want to be someone who only posts to plug his own work, but I've tackled some of these issues in SimpleSlugUpscale (http://forum.doom9.org/showthread.php?t=153860), and it seems worth mentioning here; you might benefit from digging through it (http://www.gyroshot.com/files/simpleslug/SimpleSlugUpscale.avsi). Succinct, useful comments (any comments, actually) is something I've seriously slacked off on, and with any luck will be in version 1.0, but if you take it one step at a time you might be able to get some ideas for your own resizing work.

turbojet
27th July 2010, 18:49
Thanks, hat's progress but my ultimate goal is getting a function that doesn't require user interaction for each source. I'm surprised there isn't a function like this already considering the rising popularity in cli encoding yet still a gui is required to crop/resize.

To do this I'm pretty sure PAR needs to be figured out, then autocrop(0) needs to be called (boolean to disable/enable autocrop) then resize based on both.

I've never created any function outside of stringing together common functions like crop, ivtc, etc. so this is all new to me. This function came from this post (http://forum.doom9.org/showthread.php?p=209339#post209339) which outputs any number which is a problem for avisynth. I added nh=(nhtemp+4)/8*8 to ensure mod8 output.

I also found this function (http://forum.doom9.org/showthread.php?p=1111789#post1111789) which gets PAR/DAR but no idea on how to stitch it all together in to a working function. Help in this area would be greatly appreciated.

Also the height idea is an interesting one and might be useful for others but would do me no good and how would someone differentiate between choosing width or height?

Gavino
27th July 2010, 19:48
To make it mod 8, I think--someone correct me if I'm wrong here--you need to add the Round(), as I did, after dividing by your desired multiple. Otherwise the floating point result of that division just gets multiplied by the mod value and you end up right back where you started.
Your version needs round() because you calculate nhtemp as a float and use floating point divide in calculating nh. In turbojet's version, nhtemp was already an int (because of floor()), so nh was calculated by integer division (after adding 4 to get the rounding effect).

Yes, those eval's were pretty gross.
The last line could also be written even more simply as
Apply(resizer + "Resize", c,newwidth,nh)

Robert Martens
27th July 2010, 23:11
In turbojet's version, nhtemp was already an int (because of floor()), so nh was calculated by integer division (after adding 4 to get the rounding effect).

The last line could also be written even more simply as
Apply(resizer + "Resize", c,newwidth,nh)

Thanks for these two comments; obviously I'll need to double check my own work on the subject of resizing, as I thought for sure I had tried using integer mathematics to achieve what I wanted, but dismissed it as ineffective for some reason. I guess I was wrong, I'll go back and review what I've been doing.

Regarding Apply, yours is the first example I've gotten to do anything. The one in the manual doesn't work, and only now do I see it's because it doesn't pass the name of the clip through to the resizer. I never noticed that, despite reading the manual three dozen times over the past few months, and making the change has Apply working without a hitch. I'm an idiot.

...my ultimate goal is getting a function that doesn't require user interaction for each source. I'm surprised there isn't a function like this already considering the rising popularity in cli encoding yet still a gui is required to crop/resize.

To do this I'm pretty sure PAR needs to be figured out...

That's my goal, too, but as far as I can tell from what I've read, pixel aspect ratio isn't an implicit property of a video stream, nor is it something all file containers can be flagged with (those that allow it don't necessarily have the info, either). If someone comes up with an elegant solution for this, I'd love to know, but for the time being you could take an approach like mine and use a conditional cascade. Taking Gavino's advice and going back to your original approach, you could try something like this:


function AutoResizeMod8(clip c,int newwidth,string resizer,float "PARin",bool "widein") {

widein= Default(widein, false)
PARin = Default(PARin, widein==true ? c.Height()==576 ? 118.0/81.0 :
\ c.Height()==480 ? 40.0/33.0 :
\ 4.0/3.0 :
\ c.Height()==576 && (c.Width()==720||c.Width()==704) ? 59.0/54.0 :
\ c.Height()==480 && (c.Width()==720||c.Width()==704) ? 10.0/11.0 : 1.0)

nhtemp = Floor(c.Height() * newwidth / (c.Width() * PARin))
nh = (nhtemp + 4) / 8 * 8

Apply(resizer + "Resize",c,newwidth,nh)

}


This allows for the auto detection of a couple of common types of input, but can't cover everything, and adds another parameter for the user to toggle, requiring them to know if they have anamorphic widescreen input. Obviously it's not perfect, and all I did was pull a chunk of script out of SSU, so I'm only showing you how to do things the way I do them; sorry I can't be of more substantial help, but I'm in the same boat as far as never having written a full-on function before. SimpleSlug's my first attempt, so it's bound to be less than ideal in its approach.

Gavino
28th July 2010, 00:19
Regarding Apply, yours is the first example I've gotten to do anything. The one in the manual doesn't work, and only now do I see it's because it doesn't pass the name of the clip through to the resizer. I never noticed that, despite reading the manual three dozen times over the past few months, and making the change has Apply working without a hitch. I'm an idiot.
Don't feel bad, I never noticed it either till you pointed it out.
I've updated the wiki to correct the example.

turbojet
4th August 2010, 05:01
Thanks Robert Martens that script works great with 16:9 NTSC sources when widein=true however I'm having a problem with 4:3 NTSC sources.

A 1.33:1 movie came out as 640x432 instead of 640x480 with this avs:
autocrop(0) #crop(2,0,716,480)
AutoResizeMod8(640,"Lanczos",widein=false)

A 2.49:1 letterboxed movie came out as 640x232 instead of 640x256 with this avs:
autocrop(0) #crop(2,108,716,262)
AutoResizeMod8(640,"Lanczos",widein=false)

Any thoughts on how to fix this?

Also with non 1:1 PAR sources I almost always use dgindex which gives some maybe useful info in the d2v file.
Aspect_Ratio=4:3
Picture_Size=720x480

I think I can figure out how to use that info for your function in a batch script. However I sometimes use virtualdub which doesn't have a sufficient cli interface. Do you know how this information could be used with your function? Maybe with a d2v parameter which is avs filename+.d2v by default.

Robert Martens
4th August 2010, 05:37
The seemingly strange dimensions are an easy explanation, in that you're cropping first; the video goes into AutoCrop before it hits the resize function, so what's happening makes sense but isn't what you think you want.

The process is, using the first clip as an example, that you crop to 716x480, then go into AutoResizeMod8. The frame size doesn't match any of the predefined pixel aspect ratios, so PARin falls back to 1.0.

nhtemp then becomes Floor(480 * 640 / (716 * 1.0)) = 429, and nh turns into 432.

One possibility, perhaps the simplest, is to crop after the mod 8 resize:


AutoResizeMod8(640,"Lanczos",widein=false)
AutoCrop(0)


Full size input for AutoResizeMod8 will allow the conditional statement to detect 720x480 and, taking widein=false into account, assign the proper pixel aspect of 10.0/11.0.

On the other hand, if you have a need to crop beforehand, you'll need to specify PARin=10.0/11.0 by hand, and don't bother with widein:


AutoCrop(0)
AutoResizeMod8(640,"Lanczos",PARin=10.0/11.0)


When defining a custom pixel aspect using this script, you should forget about widein even if the input is anamorphic. The widein parameter only works if the input is 720x480, 704x480, 720x576, 704x576, or 1440x1080. If you've cropped the clip beforehand, that goes right out the window, and the parameter is useless. You'll need to define the pixel aspect by hand as 40.0/33.0 (for wide NTSC DV; wide PAL would be 118.0/81.0).

The correct output size here would be 640x472:


nhtemp = Floor(480 * 640 / (716 * 10.0 / 11.0))
nh = (471 + 4) / 8 * 8


The display aspect of the cropped input is (716 * 10.0 / 11.0) / 480 = 1.356061. The output is assumed to be square pixel, so that means the DAR of the output is 640 / 472 = 1.355932, which for mod 8 is as close as you're going to get to the input DAR.

As for using the d2v info in VirtualDub, I'll need to do some thinking on the subject. It sounds like an interesting possibility, but off the top of my head I don't have an answer.

turbojet
9th August 2010, 12:27
Cropping after the resize won't work because more often than not it won't be 640x as specified.

How about inserting autocrop into the function and use it after the aspect ratio is figured out but before resizing?

Robert Martens
9th August 2010, 21:22
That's such a blindingly obvious problem that I can only think I was sleep deprived the night before I typed up that post. You're right, of course, and your solution works as you'd expect:


function AutoResizeMod8(clip c,int newwidth,string resizer,float "PARin",bool "widein") {

widein= Default(widein, false)
PARin = Default(PARin, widein==true ? c.Height()==576 ? 118.0/81.0 :
\ c.Height()==480 ? 40.0/33.0 :
\ 4.0/3.0 :
\ c.Height()==576 && (c.Width()==720||c.Width()==704) ? 59.0/54.0 :
\ c.Height()==480 && (c.Width()==720||c.Width()==704) ? 10.0/11.0 : 1.0)

nhtemp = Floor(c.Height() * newwidth / (c.Width() * PARin))
nh = (nhtemp + 4) / 8 * 8

AutoCrop(c,0)

Apply(resizer + "Resize",last,newwidth,nh)

}


Add the AutoCrop() call specifying "c" as the clip, then change "c" in the Apply() to "last" and the output is properly sized and cropped as necessary.