# MultiSWAR - Multi Step Warping And Resizing - V1 Beta3
#
#A modified version of LimitedSharpenFaster is included in this script
#

LoadPlugin("WarpSharp.dll")
LoadPlugin("aWarpSharp.dll")
LoadPlugin("GradFun2db.dll")
LoadPlugin("FrFun7.dll")
LoadPlugin("Addgrain.dll")
LoadPlugin("mt_masktools.dll")
LoadPlugin("RemoveGrain.dll")

function LimitedSharpenFaster( clip clp, 
 \                       float "ss_x",   float "ss_y", 
 \                       int   "dest_x", int   "dest_y",
 \                       int   "Smode" , int   "strength", int  "radius", 
 \                       int   "Lmode",  bool  "wide",     int  "overshoot", int "undershoot",
 \                       int   "soft",   int   "edgemode", bool "special",
 \                       int   "exborder" )
{
ox = clp.width
oy = clp.height

Smode     = default( Smode,       3 )
ss_x      = (Smode==4)
 \        ? default( ss_x,      1.25)
 \        : default( ss_x,      1.5 )
ss_y      = (Smode==4)
 \        ? default( ss_y,      1.25)
 \        : default( ss_y,      1.5 )
dest_x    = default( dest_x,     ox )
dest_y    = default( dest_y,     oy )
strength  = (Smode==1)
 \        ? default( strength,  160 )
 \        : default( strength,  100 )
strength  = (Smode==2&&strength>100) ? 100 : strength
radius    = default( radius,      2 )
Lmode     = default( Lmode,       1 )
wide      = default( wide,    false )
overshoot = default( overshoot, 1)
undershoot= default( undershoot, overshoot)
softdec   = default( soft,        0 )
soft    =  softdec!=-1 ? softdec : sqrt( (((ss_x+ss_y)/2.0-1.0)*100.0) ) * 10
soft    = soft>100 ? 100 : soft
edgemode  = default( edgemode,    0 )
special   = default( special, false )
exborder  = default( exborder, 0)
#radius =   round( radius*(ss_x+ss_y)/2)  #  If it's you, Mug Funky - feel free to activate it again  
xxs=round(ox*ss_x/8)*8
yys=round(oy*ss_y/8)*8
smx=exborder==0?dest_x:round(dest_x/Exborder/4)*4
smy=exborder==0?dest_y:round(dest_y/Exborder/4)*4

clp.isYV12() ? clp : clp.converttoyv12()

ss_x != 1.0 || ss_y != 1.0 ? last.Spline36Resize(xxs,yys) : last
tmp = last

edge = mt_logic( tmp.mt_edge(thY1=0,thY2=255,"8 16 8 0 0 0 -8 -16 -8 4")
 \              ,tmp.mt_edge(thY1=0,thY2=255,"8 0 -8 16 0 -16 8 0 -8 4")
 \              ,"max") .mt_lut("x 128 / 0.86 ^ 255 *") #.levels(0,0.86,128,0,255,false) 

tmpsoft       = tmp.removegrain(11,-1)
dark_limit1   = tmp.mt_inpand()
bright_limit1 = tmp.mt_expand()
dark_limit    = (wide==false) ? dark_limit1   : dark_limit1  .removegrain(20,-1).mt_inpand()
bright_limit  = (wide==false) ? bright_limit1 : bright_limit1.removegrain(20,-1).mt_expand() 
minmaxavg     = special==false
 \            ? mt_average(dark_limit1, bright_limit1)
 \            : mt_merge(dark_limit,bright_limit,tmp.removegrain(11,-1),Y=3,U=-128,V=-128)

Str=string(float(strength)/100.0)
normsharp = Smode==1 ? unsharpmask(strength,radius,0) 
 \        : Smode==2 ? sharpen(float(strength)/100.0) 
 \        : Smode==3 ? mt_lutxy(tmp,minmaxavg,yexpr="x x y - "+Str+" * +")
 \        :            mt_lutxy(tmp,tmpsoft,"x y == x x x y - abs 16 / 1 2 / ^ 16 * "+Str+
 \                       " * x y - 2 ^ x y - 2 ^ "+Str+" 100 * 25 / + / * x y - x y - abs / * + ?")

OS = string(overshoot)
US = string(undershoot)
mt_lutxy( bright_limit, normsharp, yexpr="y x "+OS+" + < y x y x - "+OS+" - 1 2 / ^ + "+OS+" + ?")
mt_lutxy( dark_limit, last, yexpr="y x "+US+" - > y x x y - "+US+" - 1 2 / ^ - "+US+" - ?")

Lmode==1 ? mt_clamp(normsharp, bright_limit, dark_limit, overshoot, undershoot) : last
 
normal = last
zero   = mt_clamp(normsharp, bright_limit, dark_limit, 0,0)

Lmode==3 ? mt_merge(normal,zero,edge.mt_inflate()) : normal

      edgemode==0  ?  last 
 \  : edgemode==1  ?  mt_merge(tmp,last,edge.mt_inflate().mt_inflate().removegrain(11,-1),Y=3,U=1,V=1)
 \  :                 mt_merge(last,tmp,edge.mt_inflate().mt_inflate().removegrain(11,-1),Y=3,U=1,V=1)

AMNT  = string(soft)
AMNT2 = string(100-soft)
sharpdiff=mt_makediff(tmp,last)
sharpdiff2=mt_lutxy(sharpdiff,sharpdiff.removegrain(19,-1),
 \           "x 128 - abs y 128 - abs > y "+AMNT+" * x "+AMNT2+" * + 100 / x ?")

soft==0 ? last : mt_makediff(tmp,sharpdiff2)
  
     (ss_x != 1.0 || ss_y != 1.0) 
\ || (dest_x != ox || dest_y != oy) ? Spline36Resize(dest_x,dest_y) : last

ex=blankclip(last,width=smx,height=smy,color=$FFFFFF).addborders(2,2,2,2).coloryuv(levels="TV->PC")
 \.blur(1.3).mt_inpand().blur(1.3).bicubicresize(dest_x,dest_y,1.0,.0)
tmp =  clp.Spline36Resize(dest_x,dest_y)

clp.isYV12() ? ( exborder==0 ? tmp.mergeluma(last)
 \                           : mt_merge(tmp,last,ex,Y=3,U=1,V=1) )
 \           : ( exborder==0 ? tmp.mergeluma(last.converttoyuy2())
 \                           : tmp.mergeluma( mt_merge(tmp.converttoyv12(),last,ex,Y=3,U=1,V=1)
 \                                           .converttoyuy2()) )
 
(edgemode!= -1) ? last : edge.Spline36Resize(dest_x,dest_y).greyscale

return last
}

Function MultiSWAR(Clip Clp,Int"DestX",Int"DestY",Int"StepRatio",Int"Sharpen",Int"Warping",Int"Sthresh",Int"FDetail",Bool"Sharper",Bool"Warper",Bool"Smoothing",Bool"Edetail",Bool"Smoothing2",Bool"NthPass",Float"Sstrength",Float"Sthresh2",Float"Esharp", Float"SS", Int"Smode")

{

StepRatio = Default(StepRatio,2)
Sharpen	= Default(Sharpen,100)
Warping = Default(Warping,4)
Sthresh = Default(Sthresh,128)
Sharper	= Default(Sharper,True)
Warper	= Default(Warper,True)
Smoothing = Default(Smoothing,False)
Sstrength = Default(Sstrength,1.2)
Sthresh2 = Default(Sthresh2,1.1)
EDetail = Default(Edetail,true)
Fdetail = Default(FDetail, 1)
Esharp = Default(Esharp,0.25)
NthPass = Default(NthPass, false)
Smoothing2 = Default(Smoothing2, Smoothing)
Smode = Default(Smode, 3)
SS = Default(SS, 1.25)

OX = m(16,Clp.Width)
OY = m(16,Clp.Height)

Clp.Spline36Resize(OX+round(OX/StepRatio/4)*4,OY+round(OY/StepRatio/4)*4)

Smoothing2 ? gradfun2db(thr=Sthresh2) : last

Warper ? aWarpSharp(Depth=Warping, Blurlevel=1, cm=0) : last

EDetail ? Addgrain(Fdetail, .1, .1).blur(-Esharp) : last

Sharper ? LimitedSharpenfaster(Smode=Smode, soft=8, strength=sharpen, overshoot=0, SS_X=SS, SS_Y=SS) : last

Smoothing ? FrFun7(Sstrength,Sthresh,Sthresh) : last

return (width < destx) ? MultiSWAR(DestX, DestY, Smoothing2=Smoothing2, Smoothing=NthPass, StepRatio=StepRatio, Sharpen=Sharpen, Warping=Warping, FDetail=FDetail, Sharper=Sharper, Warper=Warper, Edetail=Edetail, Sthresh2=Sthresh2, Sthresh=Sthresh, Sstrength=Sstrength, SS=SS, Smode=Smode, Esharp=Esharp/StepRatio) : lanczosresize(destx,desty)

}
function m(int r, float x) {return(x<16?16:int(round(x/float(r))*r))}