View Full Version : How make automatical resize (downscaling) with avs?
Dreamject
13th April 2019, 20:07
I'm newbe, do not hit me)
I wanna make something like downscaling to, for example, 1366/768 display
So
1) Resizing should works only as downscaling
2) Target width/height should be devided to 2 without float (resizing limitation at least in SVP)
Ideally it should be like
TargetRes="1366,768"
But
TargetWidth=1366
TargetHeight=768
is okay too
I'm not familiar with avisynth, imho it should be like
WidthDen=width/TargetWidth
HeightDen=height/TargetHeight
WidthDen OR HeightDen > 1 eval("""
WidthDen > HeightDen eval("""
cropstring="BicubicResize(round(width/WidthDen),round(height/WidthDen),b=0,c=0.75)"
""") : eval ("""
cropstring="BicubicResize(round(width/HeightDen),round(height/HeightDen),b=0,c=0.75)"
""") : cropstring=""
But them also should be rounded to bigger number than must be devided to 2
FranceBB
13th April 2019, 22:20
What you are looking for is ResizeKAR (https://forum.doom9.org/showthread.php?t=135229):
In your case, just use:
ResizeKAR(1366, 768, "BicubicResize")
By the way, I suggest you to use LanczosResize as resizing kernel over Bicubic.
# ResizeKAR() - May 8th, 2008
# Resize the source keeping the aspect ratio, by adding a border when needed.
#
# Input:
# clip c: input clip.
# int width: output width
# int height: output height
# Optional:
# string ResizeMethod: Default(BilinearResize)
# int BackgroundColor: Default($000000)
# bool NoBorders: Resizes without adding borders. Default(False)
#
# Notes:
# Respects ColorSpace Restrictions
function ResizeKAR(clip c, int width, int height, string "ResizeMethod", int "BackgroundColor", bool "NoBorders")
{
BackgroundColor = Default(BackgroundColor, $000000)
ResizeMethod = Default(ResizeMethod, "BilinearResize")
NoBorders = Default(NoBorders, False)
ratioS = Float(width(c))/Float(height(c))
ratioD = Float(width)/Float(height)
newW = Round(height*ratioS/2)*2
newH = Round(width/ratioS/2)*2
BorderH = (NoBorders==True) ? 0 : Round((height-newH)/2)
BorderW = (NoBorders==True) ? 0 : Round((width-newW)/2)
#Dest Higher Then Source; Dest Wider Then Source; Same Ratio
c =
\ (ratioS>ratioD) ?
\ Eval(ResizeMethod + "(c, " + String(width) + ", " + String(newH) + ")").
\ AddBorders(0, BorderH, 0, BorderH, BackgroundColor) :
\ (ratioS<ratioD) ?
\ Eval(ResizeMethod + "(c, " + String(newW) + ", " + String(height) + ")").
\ AddBorders(BorderW, 0, BorderW, 0, BackgroundColor) :
\ (ratioS==ratioD) ?
\ Eval(ResizeMethod + "(c, " + String(width) + ", " + String(height) + ")" ) :
\ nop()
#fix 1px changes, works only with 4:4:4
c =
\ (IsRGB(c)) && (width>width(c)) && (NoBorders==false) ? c.AddBorders(0, 0, 1, 0) :
\ (IsRGB(c)) && (height>height(c)) && (NoBorders==false) ? c.AddBorders(0, 0, 0, 1) :
\ c
return c
}
hello_hello
14th April 2019, 00:03
For the record, a simple way to round is to do this (rounded down to mod2 in this example)
floor(NonRoundedNumber / 2.0) * 2
Normally you'd crop the existing picture to 16:9 first, or resize and then add borders as required for 16:9. If the source is 16:9 already, you can just resize to 16:9 dimensions. You can crop with the resizers though, and the cropping can be float.
The function below would crop for the correct aspect ratio rather than add borders as FranceBB's function does.
function MyResizing(clip Source, int "NewWidth", int "NewHeight")
{
SourceWidth = float(width(Source))
SourceHeight = float(height(Source))
SourceAspect = SourceWidth / SourceHeight
NewWidth = default(NewWidth, 1366)
NewHeight = default(NewHeight, 768)
NewAspect = float(NewWidth) / float(NewHeight)
SourceAspect < NewAspect ? eval("""
HeightCrop = SourceHeight - (SourceWidth / NewAspect)
WidthCrop = 0
""") : SourceAspect > NewAspect ? eval("""
WidthCrop = SourceWidth - (SourceHeight * NewAspect)
HeightCrop = 0
""") : eval("""
WidthCrop = 0
HeightCrop = 0
""")
return Source.BicubicResize(NewWidth,NewHeight, \
src_left=WidthCrop/2.0, src_top=HeightCrop/2.0, \
src_width=SourceWidth-WidthCrop, src_height=SourceHeight-HeightCrop, \
b=0,c=0.75)
}
MyResizing(1366,768)
That's only been tested in my head, but it should be okay.
It's pretty much the basis of this function (https://forum.doom9.org/showthread.php?t=175114), although it can crop or add borders. Unfortunately it won't resize with BicubicResize (unless it resizes with the Resize8 script), but it'd be easy enough to find the resizing in the function and change Spline36Resize to BicubicResize. The screenshots in the opening post I linked to have gone AWOL and I haven't replaced them as there's a new version of the function on the way. It will allow the use of any resizer but I've still got a few things to test.
I've no idea how any of that would relate to SVP. I've never used it.
Dreamject
14th April 2019, 14:22
Thanks, hello_hello, I will try :)
SVP is smoothvideo project, imho the best available pc's motion interpolator. It was paid-free and free to change settings to 3* version, it becomes shareware from 4* version with free libraries, but... Even "pro" version of this is not really pro, it do not allow you to control avisynth behaviour, just has slider, which makes mostly nothing. Slider's backend should be smart, but imho, it's stupid, not optimized. So I port SVPPro to clear avs with full access muhaha
Wtf why am I must use float(number) to get correct result:mad:
hello_hello
14th April 2019, 17:11
Wtf why am I must use float(number) to get correct result:mad:
Avisynth does integer maths by default. So...
4 / 3 = 1
whereas
4.0 / 3.0 = 1.33333333
(only one needs to be float and Avisynth should convert the other to float automatically)
I don't know what you're referring to specifically, but you can specify a number as float by adding a decimal point, so 4.0 is the same as float(4). Where are you having to use float? Are you referring to SVP or your port??
Many functions require a numerator and denominator as integers.
ie AssumeFPS(24000, 1001)
I sometimes find it annoying, especially when you have to type something like FPSNum=24000, FPSDen=1001.
For my CropResize script, which has a few aspect ratio arguments, I chose to do the equivalent of Aspect=1.7777 or Aspect=16.0/9.0
It forces you to specify fractions as float though, because Aspect=16/9 would be the same as Aspect=1, and obviously wouldn't produce the expected result.
That's hopefully the explanation, although without knowing specifically what you're referring to. :)
Dreamject
14th April 2019, 19:50
:devil::devil::devil:
I though I could increase speed using resize, but ffdshow's raw filter with PP veeery slow. I've made sending avs to registry to make it usable, but it's very slow (and my current laptop slow too).
I can finish, but I wanted to friendly with svp's native functions
Originally it uses resize string for resize settings like
function interpolate(clip src)
{
input = crop_string=="" ? src : eval("src."+crop_string)
input = resize_string=="" ? input : eval("input."+resize_string)
#MT-MODE-1 #do not remove this line!
super=SVSuper(input, super_params)
vectors=SVAnalyse(super, analyse_params, src=input)
smooth=SVSmoothFps(input, super, vectors, smoothfps_params, mt=threads, src=src)
#MT-MODE-2 #do not remove this line!
return demo_mode==0 ? smooth : demo(input,smooth)
}
So I need to calculate resize sting before, as I get
NewWidth = 1366
NewHeight = 768
SourceAspect = float(source_width) / float(source_height)
MyAspect = float(NewWidth) / float(NewHeight)
SourceAspect > MyAspect ? eval("""
ResizedWidth=NewWidth
ResizedHeight=round(float(source_height) * float(NewWidth) / float(source_width) / 2.0) * 2
""") : eval("""
ResizedHeight=NewHeight
ResizedWidth=round(float(source_width) * float(NewHeight) / float(source_height) / 2.0 ) * 2
""")
resize_string="BicubicResize("+String(ResizedWidth)+","+ResizedHeight+",b=0,c=0.75)"
How to convert this to function what gives resize_string?
Also I wanted to use RoboCrop for autocroping, but it's not works in my cases https://forum.doom9.org/showthread.php?p=1633485#post1633485 .In best case it should
1 Detect black borders and remove it with auto crop
2 Check that height or width of cropped image bigger than target resolution and call resize
..but as I get I it's still be worse than PP's internal avisynth, the only advantage is autocropping
hello_hello
14th April 2019, 23:24
Can't the Interpolate() function call a function to do the resizing and give it the clip so there's no having to worry about creating strings? I assume demo() is another function too, so it's the same idea. Using the previous MyResizing() function to do the work (which is already configured to default to a 1366x768 output).
function interpolate(clip src)
{
input = src.MyResizing()
#MT-MODE-1 #do not remove this line!
super=SVSuper(input, super_params)
vectors=SVAnalyse(super, analyse_params, src=input)
smooth=SVSmoothFps(input, super, vectors, smoothfps_params, mt=threads, src=src)
#MT-MODE-2 #do not remove this line!
return demo_mode==0 ? smooth : demo(input,smooth)
}
How to convert this to function what gives resize_string?
Assuming the calculations are correct, I think you're after something like this, although with the SourceAspect stuff different.
source_width = float(width(Source))
source_height = float(height(Source))
SourceAspect = source_width / source_height
If you defined the new width, height and aspect in a similar way, you wouldn't have to type float() so much.
function ResizeString(clip Source, int "NewWidth", int "NewHeight")
{
NewWidth = default(NewWidth, 1366)
NewHeight = default(NewHeight, 768)
SourceAspect = float(source_width) / float(source_height)
MyAspect = float(NewWidth) / float(NewHeight)
SourceAspect > MyAspect ? eval("""
ResizedWidth=NewWidth
ResizedHeight=round(float(source_height) * float(NewWidth) / float(source_width) / 2.0) * 2
""") : eval("""
ResizedHeight=NewHeight
ResizedWidth=round(float(source_width) * float(NewHeight) / float(source_height) / 2.0 ) * 2
""")
return "BicubicResize("+String(ResizedWidth)+","+ResizedHeight+",b=0,c=0.75)"
}
So instead of just calling the cropped and resized clip, you'd call the ResizeString() function for the resizing and a yet to be created CropString() function for the cropping??
function interpolate(clip src)
{
input = CropString()=="" ? src : eval("src."+CropString())
input = ResizeString()=="" ? input : eval("input."+ResizeString())
#MT-MODE-1 #do not remove this line!
super=SVSuper(input, super_params)
vectors=SVAnalyse(super, analyse_params, src=input)
smooth=SVSmoothFps(input, super, vectors, smoothfps_params, mt=threads, src=src)
#MT-MODE-2 #do not remove this line!
return demo_mode==0 ? smooth : demo(input,smooth)
}
That looks about right (no promises), and hopefully it's what you're after. I'm out of time for the moment. Hopefully someone else will help further if need be, or there's always tomorrow. :)
Dreamject
16th April 2019, 06:55
Thanks, I will try it :)
hello_hello
17th April 2019, 05:53
I had another thought, although it seems odd to me the Interpolate() function always crops and resizes before it does the frame interpolation stuff. If your source is standard definition it'd be faster to interpolate frames first, then upscale.
When I use ffdshow's Avisynth filter, I usually aim to change the resolution as little as possible and then let the player upscale to fullscreen. That way you can crop if need be, but there's no need to add borders as the player will do it in fullscreen mode. I'm still not exactly sure what you're doing though. Anyway....
I also did this for myself, to see if I understand how to pass strings for cropping/resizing correctly. It seems to be working. It's much the same MyResizing() function as before, except it only creates global strings for cropping and resizing (it seems mental not to calculate them together) and passes the source through untouched.
So assuming the global environment works with the way you're doing things, you should be able to load the function and use MyResizing() before Interpolate() to create the strings. Why you'd do it that way, I'm not sure, but this might give you some ideas.
function MyResizing(clip Source, int "NewWidth", int "NewHeight") {
SourceWidth = width(Source)
SourceHeight = height(Source)
SourceAspect = float(SourceWidth) / float(SourceHeight)
NewWidth = default(NewWidth, 1366) >= SourceWidth ? SourceWidth : default(NewWidth, 1366)
NewHeight = default(NewHeight, 768) >= SourceHeight ? SourceHeight : default(NewHeight, 768)
NewAspect = float(NewWidth) / float(NewHeight)
SourceAspect < NewAspect ? eval("""
HeightCrop = round(max(0, SourceHeight - (float(SourceWidth) / NewAspect) / 2.0)) * 2
CL = 0
CT = floor(HeightCrop / 4.0) * 2
CR = 0
CB = HeightCrop - CT
""") : SourceAspect > NewAspect ? eval("""
WidthCrop = round(max(0, SourceWidth - (float(SourceHeight) * NewAspect) / 2.0)) * 2
CL = floor(WidthCrop / 4.0) * 2
CT = 0
CR = WidthCrop - CL
CB = 0
""") : eval(""" CL=0 CT=0 CR=0 CB=0 """)
global crop_string = (CL == CT == CR == CB == 0) ? "" : \
"Crop("+string(CL)+","+string(CT)+","+string(-CR)+","+string(-CB)+")"
global resize_string = (SourceWidth == NewWidth) && (SourceHeight == NewHeight) ? "" : \
"BicubicResize("+string(NewWidth)+","+string(NewHeight)+",b=0,c=0.75)"
return source }
MyResizing(640,480)
function TestingTesting(clip src) {
input = crop_string=="" ? src : eval("src."+crop_string)
input = resize_string=="" ? input : eval("input."+resize_string)
return input }
TestingTesting()
Edit1: MyResizing() changed to only downscale.
The default for NewWidth is 1366, but when NewWidth >= the source width, it's ignored.
The default for NewHeight is 768, but when NewHeight >= the source height, it's ignored.
Edit2: Fixed the cropping.
StainlessS
17th April 2019, 10:22
by HH,
If your source is standard definition it'd be faster to interpolate frames first, then upscale.
Absolutely, also interpolation will likely be better as will have shorter vectors when lower rez.
Also there is also a liimit to vector length and so upscaling beforehand would make it more likely that good vectors are sometimes not found.
EDIT: Actually, this is thread title "How make automatical resize (downscaling) with avs?"
so unless OP changed his mind, might be better to interpolate after downscale.
hello_hello
18th April 2019, 01:05
I forgot about the "only downscale" criteria. That makes more sense. So the MyResizing function would need to be modified. I'll edit my previous post and fix it.
hello_hello
18th April 2019, 11:30
My brain caught up while I was doing something else and it occurred to me the cropping was wrong. The width cropping was being cropped from both left and right. The same for height cropping. I've fixed that too.
hello_hello
18th April 2019, 20:34
Unbelievable! I changed the cropping and still got it wrong. I'm having a brain-dead day.
Dreamject
18th April 2019, 22:10
:D is seems avisynth is quite strange
Dreamject
19th April 2019, 22:32
Mostly I can't test script, cause I do not know how to avisynth on any player expect PP, it seems to difficult and unusable to test it, anyway ffdshow even in x768 does not give improvements in perfomance in my case, I watch movies from laptop not very often, I need autocrop not very often too, etc). If it's not difficult, you can use this script/library https://vk.com/doc275347426_499703245 , I add it.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.