DESCRIPTION:
BestFit() is an avisynth function designed to make a video clip (of any height and width) fit a particular resolution by:
- resizing
- adding borders, or
- cropping
COMMON USAGE:
Code: Select all
BestFit(640, 480)
BestFit(640, 480, "crop")
BestFit(640, 480, "addborders")
BestFit(848, 480)
BestFit(848, 480, "crop")
BestFit(848, 480, "addborders")
BestFit(960)
Spoiler :
BestFit( width, height, method, mod, modb, AR_in, percent, percent_area, full, DVD, wide, xwide, UNKNOWN, snap, range, gc, rs, stats )
BestFit( clip c, int "width", int "height", string "method", int "mod", int "modb", float "AR_in", int "percent", int "percent_area", float "full", float "DVD", float "wide", float "xwide", float "UNKNOWN", bool "snap", float "range", bool "gc", string "rs", int "stats" )
BestFit( clip c, int "width", int "height", string "method", int "mod", int "modb", float "AR_in", int "percent", int "percent_area", float "full", float "DVD", float "wide", float "xwide", float "UNKNOWN", bool "snap", float "range", bool "gc", string "rs", int "stats" )
Code: Select all
# VARIABLE DEFAULT VALUE OTHERS VALUES
#
# width= c.width() any integer
# height= float(width)/AR_in any integer
# AR_in= width()/height() any float
# method= "resize" "crop", "addborders", "addbottom"
# mod= 4 any integer
# modb= 1 any integer
# percent= 100 any integer
# percent_area= 100 any integer
# full= 1.333333333 any float
# DVD= 1.500000000 any float
# wide= 1.777777777 any float
# xwide= 2.350000000 any float
# UNKNOWN= AR_in any float
# snap= true false
# range= 0.08 any float [max 0.08]
# gc= false true
# rs= "spline36resize" any existing resizer
# stats= 0 1, 2
-top left = resultant width x height, ratio
-bottom left = reference to the documentation
-bottom right = command used
[WIDESCREEN SOURCE]





[FULLSCREEN SOURCE]





[DVD SOURCE]


FULL DOCUMENTATION & ADVANCED EXAMPLES:
Spoiler :
Code: Select all
################################### BestFit() ####################################
# #
# BestFit() by Phantasmagoriat #
# #
# project #
# started : April 28, 2010 #
# version updated : June 11, 2010 #
# version # : 1.0.1 #
# #
#### DESCRIPTION #################################################################
#
#
# -BestFit() is an avisynth function designed to make a video clip (of any
# height and width) fit a particular resolution by:
# resizing, adding borders, or cropping.
#
#
#
#### SETUP #######################################################################
#
#
# A. All required functions are internal, so you just need AviSynth
#
# 1. copy/paste the Script into a blank .txt file
# 2. rename it "BestFit.avsi" ( OMG your file extensions are showing! )
# 3. put it into your avisynth plugins folder:
# C:\Program Files\AviSynth 2.5\plugins <--
#
# B. you should now be able to use BestFit() in your avisynth scripts :)
#
#
#
#
#### FEATURES ####################################################################
#
# -choose your METHOD of 'fitting' a video to your desired resolution:
# "resize", "crop", "addborders", "addbottom"
# -easily scale an image by specifying a new width (height is calculated)
# -resize by PERCENT and PERCENT_AREA
# -SNAP can round height/width to the nearest common AR (default is true)
# -set new SAR (AR_in)
# -option for MODXX output (default is mod4)
# -custom GARBAGE CROP can get rid of tiny black borders (default is false)
# -user can implement their own CUSTOM RESIZER (default is spline36resize)
# -useful STATISTICS can be printed to the screen
# -contains ADDITIONAL FUNCTIONS that you may find useful
#
#
#
#### USAGE / EXAMPLES ############################################################
#
#
# For normal usage, just specify a width, height (optional), and desired
# method of fitting the clip to said width/height. The available arguments
# for Method are "resize", "crop", "addborders", and "addbottom"
#
#
# EXAMPLES: [see accompanying pictures for details]
# LETS SAY YOUR INPUT CLIP HAS A RESOLUTION OF
# 848 x 480 (~widescreen, ~16:9, ~1.77777) -->
# avisource( "your_848x480_clip.avi" ) # [A] > you want to make this 'fit' fullscreen
#
# bestfit( 640 ) # [1] > scales image to a width of 640
#
# bestfit( 1280 ) # [1.1] > scales image to a width of 1280
#
# bestfit( 640,480 ) # [2] > scales image until constrained by width or height
# same as bestfit(640,480, "resize")
#
# bestfit( 640,480, "crop" ) # [3] > sides are cropped to become 4:3
#
# bestfit( 640,480, "addborders" ) # [4] > borders added to top/bottom to be 4:3
#
# bestfit( 640,480, "addbottom" ) # [5] > borders added to 'bottom only' to be 4:3
# # [5.1] > useful for subtitles on portable devices
# bestfit( 640,480, "addborders", modb=16)# [5.2] > ensures borders are also mod16 compliant
#
#
# LETS SAY YOUR INPUT CLIP HAS A RESOLUTION OF
# 640 x 480 (fullscreen, 4:3, 1.333333) -->
# avisource( "your_640x480_clip.avi" ) # [B] > you want to make this 'fit' widescreen
#
# bestfit( 848 ) # [6] > scales image to a width of 848
#
# bestfit( 848,480 ) # [7] > scales image until constrained by width or height
# same as bestfit(848,480, "resize")
#
# bestfit( 848,480, "crop") # [8] > top/bottom cropped to become 16:9
#
# bestfit( 848,480, "addborders" ) # [9] > borders added to sides to become 16:9
#
# bestfit( 848,480, "addbottom" ) # [10] > there is no 'letterbox' to add here :|
#
#
#
# LETS SAY YOUR INPUT CLIP HAS A RESOLUTION OF
# 720 x 480 (DVD, unspecified AR ) -->
# avisource( "your_720x480_clip.avi" ) # [C] > you want to make this look correct
#
# bestfit( AR_in=1.77777 ) # [11] > [correct] treats clip as if it was 16:9
#
# bestfit( AR_in=1.33333 ) # [12] > [wrong] treats clip as if it was 4:3
#
# bestfit( 848, 480 ) # [13] > [wrong] scales image until constrained by height
#
# bestfit( 848, 480, "addborders" ) # [14] > [wrong] borders added to sides to become 16:9
#
# I guess the point I'm trying to make here is that BestFit() will never stretch
# or squish the original image unless you specify a new Aspect Ratio with AR_in. This means:
#
#
# !IT IS VERY IMPORTANT THAT YOUR FOOTAGE IS IN THE CORRECT SAR* TO BEGIN WITH!
# ( otherwise you will have to specify AR_in yourself )
# *Storage Aspect Ratio = the ratio of Width to Height in pixels
#
#
#
# LETS SAY YOUR INPUT CLIP HAS AN IRREGULAR RESOLUTION LIKE
# 640 x 488 (irregular, 80:61, 1.3115 ) -->
# avisource(" your_640x488_clip.avi" ) # [D] > you want to make it normal
#
# bestfit( mod=16, rs="bilinearresize") # [15] > resizes to mod16 values using bilinearresize
#
# bestfit( gc=true, snap=true, range=0.06)# [16] > crops 8 px from the left/right; 4 px top/bottom
# > then resizes to nearest common AR within 0.06
#
# bestfit( percent=200, stats=2 ) # [17] > scales image to 200% original width/height
# > displays full statistics about clip
#
# bestfit( percent_area=200, stats=2 ) # [18] > resizes image until it is 200% the original area
# > displays full statistics about clip
#
#
#### ADDITIONAL FUNCTIONS ########################################################
#
#
# The following are subroutines used by BestFit(), but instead of placing
# them in the body of the function, I decided to make them separate
# functions-- so if you want, you can use them too :)
#
#
# avisource("Close Encounters.avi") # [E]
# rs( 640,480 ) # [19]
# This can be used as a substitute for your favorite resizer.
# By default, it uses spline36resize, so instead of typing
# out spline36rsize( 640,480 ), you can simply type rs( 640,480 )
#
#
# avisource("futurama.avi") # [F]
# gc( 8,4 ) # [20]
# Does the same thing as crop( 8, 4, -8, -4 )
#
#
# AR_in() # [21]
# Does not return a clip,
# but rather, a float value of the SAR of your clip.
#
#
# c.getmod(w) # [22]
# Returns the highest mod value of clip c's width
#
#
# c.getmod(h) # [23]
# Returns the highest mod value of clip c's height
#
#
# crop2mod(2) # [24]
# Will crop your width and height until they comply with
# the specified mod. Useful if your clip has Odd values
# for height and/or width.
# If you simply want to make your clip modxx compliant, do not use
# this. Simply use BestFit(mod=16)
#
#
# echo( "c.getmod()", "c.AR_in()" ) # [25]
# Hopefully nobody else has a function named echo() in their plugins
# directory, otherwise avisynth will crash, but if you have ever wanted
# to print a variable to the screen, you will find it is not easy...
# [b/c Subtitle() only takes string values], so I use echo to convert the
# variable to a string, which is then passed to Subtitle() and printed.
# It's like an upgrade of Subtitle() :P
# Prints a maximum of 6 consecutive variables.
#
#
# bfstats( a, b, 2 ) # [26]
# Prints the statistics of 'clip a' and 'clip b' to the screen using
# minimum stats (1) or full stats (2)
#
#
#
#### DEFAULTS ####################################################################
#
#
# VARIABLE DEFAULT VALUE OTHERS VALUES
#
# method= "resize" "crop", "addborders", "addbottom"
# mod= 4 any integer
# modb= 1 any integer
# percent= 100 any integer
# percent_area= 100 any integer
# full= 1.333333333 any float
# DVD= 1.500000000 any float
# wide= 1.777777777 any float
# xwide= 2.350000000 any float
# UNKNOWN= AR_in any float
# snap= true false
# range= 0.08 any float [max 0.08]
# gc= false true
# rs= "spline36resize" any existing resizer
# stats= 0 1, 2
# AR_in= c.AR_in() any float
# width= c.width() any integer
# height= float(width)/AR_in any integer
#
# IF YOU WOULD LIKE TO CHANGE THE DEFAULTS FOR BESTFIT(),
# DO SO AFTER #### MAIN PROGRAM ####
#
#
#### LIMITATIONS #################################################################
#
# It has already been mentioned that BestFit() can only detect SAR (height:width in pixels)
# which can present problems if your footage uses AR flags to stretch during playback.
#
# To overcome this limitation, I am currently looking for ways to feed
# AR metadata from .d2v .mp4 .mkv etc. into avisynth so everything can be
# dealt with automatically. So far I have not found a way :(
#
#
#
#### ADDITIONAL NOTES ############################################################
#
# BestFit() was originally intended to make it easier to mix footage (of different
# sizes and aspect ratios) for video editing. Granted, it can be used for
# any situation when you require the output resolution of an image/video to
# fit a particular display or window. This makes it useful for converting
# large numbers of videos for a particular device [like my Android phone :P]
# or making thumbnails, or even quickly scaling a video to your monitor size.
#
# I should probably note that I am not a programmer... just someone who wanted
# an easier way to deal with clips of different sizes-- so this is my first avisynth
# function ever. If you have any tips, comments, suggestions, maybe even
# requests, I would gladly appreciate hearing from you.
#
#
############################################################

















- copy/paste the below script into a .txt file,
- rename to something like "BestFit().avsi"
- put it in your avisynth plugins folder, usually:
C:\Program Files\AviSynth 2.5\plugins or
C:\Program Files (x86)\AviSynth 2.5\plugins
SCRIPT:
Spoiler :
Code: Select all
#####################
#### SUBROUTINES ####
##########################################################################
function rs(
\ clip c
\, int "width"
\, int "height"
\, string "rs" )
{
rs = default( rs, "spline36resize")
eval(" c." + rs + "(width, height) ")
}
##########################################################################
function gc(
\ clip c
\, int "lr"
\, int "tb")
{
lr = default( lr, 8 )
tb = default( tb, 4 )
c.crop(lr, tb, -lr, -tb)
}
##########################################################################
function AR_in(
\ clip c )
{
float(c.width())/float(c.height())
}
##########################################################################
function getmod(
\ clip c
\, val "side"
\, int "test" )
{
side = default( side, "w" )
length = (side == "w" ) ? float(c.width())\
: float(c.height())
test = default ( test, 1 )
mod = ( Frac(length/test) != 0.0 ) ? test/2\
: getmod(c, side, test*2)
mod
}
##########################################################################
function crop2mod(
\ clip c
\, int "mod")
{
mod = default( mod, 2 )
h = c.height()
w = c.width()
hfix = ( h - ( (h/mod)*mod ) )
wfix = ( w - ( (w/mod)*mod ) )
fix = c.crop( wfix, hfix, 0, 0 )
fix
}
##########################################################################
function echo(
\ clip c
\, val "v1"
\, val "v2"
\, val "v3"
\, val "v4"
\, val "v5"
\, val "v6"
\, int "align"
\, int "x"
\, int "y"
\, float "font"
\, int "size"
\ )
{
font = default( font, "Lucida Console" )
size = default( size, 15 )
c.Subtitle(
\ String(v1)+String(v2)+String(v3)
\ +String(v4)+String(v5)+String(v6)
\, x=x, y=y, align=align, font=font, size=size )
}
##########################################################################
function bfstats(
\ clip "clip1"
\, clip "clip2"
\, int "stats"
\, val "AR_snap"
\ )
{
clip1 = default( clip1, last )
clip2 = default( clip2, last )
stats = default( stats, 1 )
AR_snap = default( AR_snap, "???" )
A = clip1 B = clip2
Aw = A.width () Bw = B.width ()
Ah = A.height() Bh = B.height()
Apx = Aw*Ah Bpx = Bw*Bh
Aperc = "100.0" Bperc = string(100*float(Bw )/float(Aw ), "%5.1f")
Aperca = "100.0" Bperca = string(100*float(Bpx)/float(Apx), "%5.1f")
c1=005 c2a=070 c2b=124 c3=180 c4=275 c5=350 c6=410
r1=005 r2 =030 r3 =045
none = B
minimum = B.\
echo( Bw," x ",Bh," SAR=",B.AR_in() ,x=c1 , y=r1 )
full = B.\
echo( "clip1:" ,x=c1 , y=r2 ).\
echo( "clip2:" ,x=c1 , y=r3 ).\
echo( "Display" ,x=c2a, y=r1 ).\
echo( Aw," x " ,x=c2a, y=r2 ).\
echo( Bw," x " ,x=c2a, y=r3 ).\
echo( Ah ,x=c2b, y=r2 ).\
echo( Bh,"**" ,x=c2b, y=r3 ).\
echo( "SAR" ,x=c3 , y=r1 ).\
echo( A.AR_in(),"*" ,x=c3 , y=r2 ).\
echo( B.AR_in() ,x=c3 , y=r3 ).\
echo( "#pix" ,x=c4 , y=r1 ).\
echo( Apx ,x=c4 , y=r2 ).\
echo( Bpx ,x=c4 , y=r3 ).\
echo( "%" ,x=c5 , y=r1 ).\
echo( Aperc ,x=c5 , y=r2 ).\
echo( Bperc ,x=c5 , y=r3 ).\
echo( "%(Area)" ,x=c6 , y=r1 ).\
echo( Aperca ,x=c6 , y=r2 ).\
echo( Bperca ,x=c6 , y=r3 ).\
echo( " *AR_snap = ", AR_snap ,x=008, y=70 ).\
echo( "**mod(width) = ",B.getmod("w"),x=008, y=85 ).\
echo( " mod(height) = ",B.getmod("h"),x=008, y=100 )
err_stat="""
BestFit() stats can only be: 0, 1, or 2
"(0)none" "(1)minimum" "(2)full"
"""
stats = ( stats == 0 ) ? none :\
( stats == 1 ) ? minimum:\
( stats == 2 ) ? full :\
assert(1==0,err_stat)
stats
}
##################################################################################
######################
#### MAIN PROGRAM ####
######################
##########################################################################
function BestFit(
\ clip c
\, int "width"
\, int "height"
\, string "method"
\, int "mod"
\, int "modb"
\, float "AR_in"
\, int "percent"
\, int "percent_area"
\, float "full"
\, float "DVD"
\, float "wide"
\, float "xwide"
\, float "UNKNOWN"
\, bool "snap"
\, float "range"
\, bool "gc"
\, string "rs"
\, int "stats"
\ )
{
#### DEFAULT VARIABLES AND COMMON VALUES ################################
c = default ( c.crop2mod(2) )
method = default ( method, "resize" )
mod = default ( mod, 4 )
modb = default ( modb, 1 )
AR_in = default ( AR_in, c.AR_in )
width = default ( width, c.width() )
height = default ( height, float(width)/AR_in )
percent = default ( percent, 100 )
percent_area = default ( percent_area, 100 )
full = default ( full, 1.333333333 )
DVD = default ( DVD, 1.500000000 )
wide = default ( wide, 1.777777777 )
xwide = default ( xwide, 2.350000000 )
UNKNOWN = default ( UNKNOWN, AR_in )
snap = default ( snap, true )
range = default ( range, 0.08 )
gc = default ( gc, false )
rs = default ( rs, "spline36resize" )
stats = default ( stats, 0 )
#########################################################################
AR_out = float(width)/float(height)
AR_snap =
\ ( ( full-range) < AR_in <= (full +range) ) ? full
\: ( ( DVD-range) < AR_in < (DVD +range) ) ? DVD
\: ( ( wide-range) <= AR_in < (wide +range) ) ? wide
\: ( (xwide-range) <= AR_in < (xwide+range) ) ? xwide
\: UNKNOWN
AR_in = ( snap == true ) ? AR_snap: AR_in
rsf = ( percent_area == 100 ) ? float(percent)/100
\ : sqrt(float(percent_area)/100)
width_calc = round( float( rsf*height*AR_in )/mod )*mod
height_calc = round( float( rsf*width /AR_in )/mod )*mod
width = round( float( rsf*width )/mod )*mod
height = round( float( rsf*height )/mod )*mod
wr = ( AR_in <= AR_out ) ? width_calc : width
hr = ( AR_in <= AR_out ) ? height : height_calc
wc = ( AR_in <= AR_out ) ? width : width_calc
hc = ( AR_in <= AR_out ) ? height_calc : height
bh = ( modb == 1 ) ? (width- wr)/2 : round(float((width- wr)/2)/modb)*modb
bv = ( modb == 1 ) ? (height-hr)/2 : round(float((height-hr)/2)/modb)*modb
wr = ( modb == 1 ) ? wr : width- (2*bh)
hr = ( modb == 1 ) ? hr : height-(2*bv)
ch = (wc- width)/2
cv = (hc-height)/2
c = ( gc == true ) ? c.gc() : c
err_met =
\"""
The only supported methods for BestFit() are:
"resize" "crop" "addborders" and "addbottom"
"""
Fit = (method == "resize" ) ? c.rs(wr, hr, rs)
\: (method == "crop" ) ? c.rs(wc, hc, rs).crop(ch,cv,-ch,-cv)
\: (method == "addborders" ) ? c.rs(wr, hr, rs).addborders(bh,bv,bh,bv)
\: (method == "addbottom" ) ? c.rs(wr, hr, rs).addborders(00,0,00,2*bv)
\: assert(1==0,err_met)
bfstats(c, Fit, stats, AR_snap)
}
__END__
#### END OF CODE ################################################################
Code: Select all
v1.0.0 - BestFit() made public
v1.0.1 - added 'modb' to allow borders to be modXX compliant [Ala Qyot]
- added useful lists: Changelog, TODO, and Known Bugs
Code: Select all
- find ways to serve AR metadata from .d2v .mp4 .mkv files into avisynth to determine DAR
- figure out algorithm to compensate for Active Picture Region [Ala Mister Hatt]
- put subroutines into main code to avoid conflict with other scripts
- clean up bulky, unnecessary code
- add color parameter for borders
- "polaroid" "fillcrop" methods
- add DVD AR parameter
Code: Select all
v1.0.1 - no known bugs ATM. Please report any.
##################################################################################
If you didn't read everything, I'll repeat here that BestFit() only detects height and width (SAR), so I am looking for ways to feed AR metadata from .dv2 .mp4 .mkv files into avisynth so that DAR can be detected. If you have any ideas, let me know.
Lastly, this is my first avisynth function, and mirko is probably the only other person to see this (thanks

~Phan