Resize Abuser
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
|
Negative values in zoomFactor is the zoom of the pixels, positive values in zoomFactor is the zoom of the frame. The code for x2,y2 is quite odd... but it seems to work for the tests that I put it through. Had to map it out, then create a formula to match the offset. As for why *2.0 in x1,y1 works... dumb luck?
Please test this sucker out. It's good to go, as far as I can tell.
Code:
A = ColorBars().Crop(10, 20, -30, -400).ConvertToYV12()
B = ColorBars().invert().FlipHorizontal().Crop(10, 20, -300, -40).ConvertToYV12()
C = ColorBars().FlipVertical().Crop(10, 200, -30, -40).ConvertToYV12()
D = ColorBars().invert().FlipVertical().FlipHorizontal().Crop(100, 20, -30, -40).ConvertToYV12()
E = ImageReader("testp2cz4.png",0,0)
E1 = E.ConvertToYV12().AssumeFPS("ntsc_video")
Global W = 640
Global H = 480
Global DAR = 0 #16.0/9.0
Global Resize = "BilinearResize"
SplitScreener(W, H, 8, A, B, C, D, ZoomToFill=1).Trim(0,-1).KillAudio()
last + SplitScreener(W, H, 8, A, B, C, D, ZoomToFill=-1).Trim(0,-1).KillAudio()
last + TestC(E1)
#Try different image
E = ImageReader("traingr4.jpg",0,0)
E2 = E.ConvertToYV12().AssumeFPS("ntsc_video")
Global DAR = 16.0/9.0
last + TestC(E2)
Return Last
#E1.ZoomBoxer(W,H, Resize, DisplayAR=0, Align=1, zoomFactor=-100, panX=0, panY=0)
Function TestC(Clip E)
{
TestA(E,-1)
last + TestA(E,-2)
last + TestA(E,-3)
last + TestA(E,-4)
last + TestA(E,-5)
last + TestA(E,5)
last + TestA(E,-6)
last + TestA(E,-7)
last + TestA(E,-8)
last + TestA(E,-9)
last + TestB(E, 25)
last + TestB(E, 50)
last + TestB(E, 75)
}
Function TestA(clip E, int al)
{
E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=100, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=75, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=50, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=25, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=12.5, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=6.25, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=3.125, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=75, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=100, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=200, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=400, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=600, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=800, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=2000, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=al, zoomFactor=20000, panX=0, panY=0)
}
Function TestB(clip E, int zf)
{
E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-5, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-1, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-3, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-7, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-9, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-2, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-4, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-6, zoomFactor=zf, panX=0, panY=0)
last + E.ZoomBoxer(W,H, Resize, DisplayAR=DAR, Align=-8, zoomFactor=zf, panX=0, panY=0)
}
Function ZoomBoxer(clip c, int "width", int "height", string "ResizeMethod", float "DisplayAR", int "Align", float "zoomFactor", float "panX", float "panY", int "color", int "IgnoreAR")
{
#set defaults
ResizeMethod = Default(ResizeMethod, "BilinearResize")
IgnoreAR = Default(IgnoreAR, 1)
color = Default(color, $000000)
width = Default(width, c.width())
height = Default(height, c.height())
Align = Default(Align, 0)
zoomFactor = Default(zoomFactor, 100.0)
#zoomFactor = -(Log(zoomFactor*0.01)/Log(4))
panX = Default(panX, 0)
panY = Default(panY, 0)
modzoom = Max(Float(c.width())/Float(width),Float(c.height())/Float(height))
zoomFactor = zoomFactor<0 ? (abs(zoomFactor)/100.0)*modzoom : (abs(zoomFactor)/100.0)
SourceAR = float(c.width())/float(c.height())
FinalAR = float(width)/float(height)
DisplayAR = Default(DisplayAR, Float(c.width())/Float(c.height()))
DisplayAR = DisplayAR == 0 ? Float(c.width())/Float(c.height()) : DisplayAR
#If Align=5 or -5 then center clip. -5: Add borders. 5: Crop.
#Display Aspect Ratio = Final Output Ratio. No Change, Show All Pixels
#Display Aspect Ratio > Final Output Ratio. Add Height or Crop Width
#Display Aspect Ratio < Final Output Ratio. Add Width or Crop Height
EvalString =
\ Align<>0 && DisplayAR==FinalAR ?
\ "x1=0" + "
x2=" + String(c.width()) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==-5 || Align==-4 || Align==-6) && DisplayAR>FinalAR ?
\ "y1=" + String(0 - ((height*DisplayAR-width)/2.0)*(c.height()/Float(width))) + "
y2=" + String(c.height() + ((height*DisplayAR-width)/2.0)*(c.height()/Float(width))) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==5 || Align==2 || Align==8) && DisplayAR>FinalAR ?
\ "x1=" + String(0 + ((height-width/DisplayAR)/2.0)*(c.width()/Float(height))) + "
x2=" + String(c.width() - ((height-width/DisplayAR)/2.0)*(c.width()/Float(height))) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==-5 || Align==-2 || Align==-8) && DisplayAR<FinalAR ?
\ "x1=" + String(0 - ((width/DisplayAR-height)/2.0)*(c.width()/Float(height))) + "
x2=" + String(c.width() + ((width/DisplayAR-height)/2.0)*(c.width()/Float(height))) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==5 || Align==4 || Align==6) && DisplayAR<FinalAR ?
\ "y1=" + String(0 + ((width-height*DisplayAR)/2.0)*(c.height()/Float(width))) + "
y2=" + String(c.height() - ((width-height*DisplayAR)/2.0)*(c.height()/Float(width))) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==-1 || Align==-2 || Align==-3) && DisplayAR>FinalAR ?
\ "y1=" + String(0) + "
y2=" + String(c.height() + ((height*DisplayAR-width)/1.0)*(c.height()/Float(width))) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==-1 || Align==-4 || Align==-7) && DisplayAR<FinalAR ?
\ "x1=" + String(0) + "
x2=" + String(c.width() + ((width/DisplayAR-height)/1.0)*(c.width()/Float(height))) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==-9 || Align==-8 || Align==-7) && DisplayAR>FinalAR ?
\ "y1=" + String(0 - ((height*DisplayAR-width)/1.0)*(c.height()/Float(width))) + "
y2=" + String(c.height()) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==-9 || Align==-6 || Align==-3) && DisplayAR<FinalAR ?
\ "x1=" + String(0 - ((width/DisplayAR-height)/1.0)*(c.width()/Float(height))) + "
x2=" + String(c.width()) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==2 || Align==1 || Align==3) && DisplayAR<FinalAR ?
\ "y1=" + String(0) + "
y2=" + String(c.height() - ((width-height*DisplayAR)/1.0)*(c.height()/Float(width))) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==8 || Align==7 || Align==9) && DisplayAR<FinalAR ?
\ "y1=" + String(0 + ((width-height*DisplayAR)/1.0)*(c.height()/Float(width))) + "
y2=" + String(c.height()) + "
x1=0" + "
x2=" + String(c.width())
\ : (Align==4 || Align==1 || Align==7) && DisplayAR>FinalAR ?
\ "x1=" + String(0) + "
x2=" + String(c.width() - ((height-width/DisplayAR)/1.0)*(c.width()/Float(height))) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : (Align==6 || Align==3 || Align==9) && DisplayAR>FinalAR ?
\ "x1=" + String(0 + ((height-width/DisplayAR)/1.0)*(c.width()/Float(height))) + "
x2=" + String(c.width()) + "
y1=0" + "
y2=" + String(c.height()) + ""
\ : ""
Eval(EvalString)
#Take Crop Like Input
x2 = x2<=x1 && x2 < 0 ? c.width() + x2 : x2
y2 = y2<=y1 && y2 < 0 ? c.height() + y2 : y2
#Check if x2 or y2 needs to be calculated
Assert( ((x2==x1) && (y2==y1))==False, "x2 [" + String(x2) + "] or y2 [" + String(y2) + "] needs a value that is different from x1 [" + String(x1) + "] or y1 [" + String(y1) + "]")
y2 = (y2==y1) ? (((x2-x1)/FinalAR)/(SourceAR/DisplayAR) + y1) : y2
x2 = (x2==x1) ? (((y2-y1)*FinalAR)*(SourceAR/DisplayAR) + x1) : x2
SubString = "Align=" + String(Align) + " zoomFactor=" + String(zoomFactor*100) + " panX=" + String(panX) + " panY=" + String(panY)
#Calc Pan Factor
x1 = x1+panX
y1 = y1+panY
x2 = x2+panX
y2 = y2+panY
#Calc Zoom Factor
BoxAR = Float(x2-x1)/Float(y2-y1)
CenterX = (x2-x1)/2.0
CenterY = (y2-y1)/2.0
CenterY = (Align<0 && DisplayAR>FinalAR)? CenterY*(FinalAR/DisplayAR): (Align>0 && DisplayAR<FinalAR)? CenterY*(FinalAR/DisplayAR): CenterY
CenterX = (Align>0 && DisplayAR>FinalAR)? CenterX/(FinalAR/DisplayAR): (Align<0 && DisplayAR<FinalAR)? CenterX/(FinalAR/DisplayAR): CenterX
Align = abs(Align)
sY = " CenterY: " + String(CenterY) + " y2: " + String(y2) + " y1: " + String(y1)
sX = " CenterX: " + String(CenterX) + " x2: " + String(x2) + " x1: " + String(x1)
x1 = (Align==0 || Align==5 || Align==2 || Align==8) && zoomFactor<>1 ? CenterX-((CenterX-x1)/(zoomFactor)) : (Align==3 || Align==6 || Align==9) && zoomFactor<>1 ? CenterX*2.0-((CenterX*2.0-x1)/zoomFactor) : x1
y1 = (Align==0 || Align==5 || Align==4 || Align==6) && zoomFactor<>1 ? CenterY-((CenterY-y1)/(zoomFactor)) : (Align==7 || Align==8 || Align==9) && zoomFactor<>1 ? CenterY*2.0-((CenterY*2.0-y1)/zoomFactor) : y1
x2 = (Align==0 || Align==5 || Align==2 || Align==8) && zoomFactor<>1 ? CenterX+((x2-CenterX)/(zoomFactor)) : (Align==7 || Align==4 || Align==1) && zoomFactor<>1 ? CenterX+((x2-CenterX)/(zoomFactor))+((100.0/(zoomFactor*100.0))-1)*CenterX : x2
y2 = (Align==0 || Align==5 || Align==4 || Align==6) && zoomFactor<>1 ? CenterY+((y2-CenterY)/(zoomFactor)) : (Align==3 || Align==2 || Align==1) && zoomFactor<>1 ? CenterY+((y2-CenterY)/(zoomFactor))+((100.0/(zoomFactor*100.0))-1)*CenterY : y2
BoxAR = Float(x2-x1)/Float(y2-y1)
#Check For Any Unreasonable Inputs
Assert(x1<x2, "ZoomBox: x1[" + String(x1) + "] point larger then x2 Point[" + String(x2) + "]")
Assert(y1<y2, "ZoomBox: y1[" + String(y1) + "] point larger then y2 Point[" + String(y2) + "]")
Assert(IgnoreAR>0 || BoxAR == FinalAR, "ZoomBox: Box Aspect Ratio [" + String(BoxAR) + "] does not equal clip output Aspect Ratio [" + string(FinalAR) + "]")
#Pad clip so resizer interpolates from border when zooming out. 64 for spline64
#Conditional Borders... only add if it's going to be used.
borderSize = 64
borderLeft = x1 < 0 ? borderSize : 0
borderTop = y1 < 0 ? borderSize : 0
borderRight = x2 > c.width() ? borderSize : 0
borderBottom = y2 > c.height() ? borderSize : 0
c = c.AddBorders(borderLeft,borderTop,borderRight,borderBottom,color)
#Do it
c = Eval(ResizeMethod + "(c, " + String(Round(width)) + ", " + String(Round(height)) + ", src_left=" + String(x1+borderLeft) + ", src_top=" + String(y1+borderTop) + ", src_width=" + String(x2-x1) + ", src_height=" + String(y2-y1) + ")")
c
Subtitle("BoxAR " + String(BoxAR) + " " + String(x1) + ", " + String(y1) + " " + String(x2) + ", " + String(y2) + " " + String())
Subtitle(SubString, y=100)
Subtitle(sY, y=140)
Subtitle(sX, y=160)
}
function SplitScreener(int Width, int Height, int Border, clip A, clip B, clip C, clip D, int "ZoomToFill", string "ResizeMethod", bool "AudioMix")
{
#Set Defaults
ResizeMethod = Default(ResizeMethod, "BilinearResize")
AudioMix = Default(AudioMix, true)
ZoomToFill = Default(ZoomToFill, -1)
#Check Inputs
Assert(ZoomToFill==1 || ZoomToFill==-1, "ZoomToFill must be 1 or -1. Input of " + String(ZoomToFill) + " doesn't work")
#Set Borders
BorderH = Border
BorderW = Border
#Set Width and Height of individual clips
NewW = Round(float(Width)/2.0 - float(BorderW)*1.5)
NewH = Round(float(Height)/2.0 - float(BorderH)*1.5)
NewAR = Float(NewW)/Float(NewH)
OutAR = Float(Width)/Float(Height)
#Process Video
A = A.ZoomBoxer(NewW, NewH, ResizeMethod, Float(A.width())/Float(A.height())*(NewAR/OutAR), ZoomToFill*(9))
A = A.AddBorders(BorderW, BorderH, 0, 0)
B = B.ZoomBoxer(NewW, NewH, ResizeMethod, Float(B.width())/Float(B.height())*(NewAR/OutAR), ZoomToFill*(7))
B = B.AddBorders(BorderW, BorderH, 0, 0)
C = C.ZoomBoxer(NewW, NewH, ResizeMethod, Float(C.width())/Float(C.height())*(NewAR/OutAR), ZoomToFill*(3))
C = C.AddBorders(BorderW, BorderH, 0, 0)
D = D.ZoomBoxer(NewW, NewH, ResizeMethod, Float(D.width())/Float(D.height())*(NewAR/OutAR), ZoomToFill*(1))
D = D.AddBorders(BorderW, BorderH, 0, 0)
#Merge Clips
X = StackHorizontal(A, B).AddBorders(0,0,BorderW,0)
Y = StackHorizontal(C, D).AddBorders(0,0,BorderW,0)
StackVertical(X, Y).AddBorders(0,0,0,BorderH).KillAudio()
#Fix Audio
LongestClip = Int(Max(Framecount(A), Framecount(B), Framecount(C), Framecount(D)))
A = (Framecount(A) <> LongestClip) ? A ++ BlankClip(A, LongestClip-Framecount(A)) : A
B = (Framecount(B) <> LongestClip) ? B ++ BlankClip(B, LongestClip-Framecount(B)) : B
C = (Framecount(C) <> LongestClip) ? C ++ BlankClip(C, LongestClip-Framecount(C)) : C
D = (Framecount(D) <> LongestClip) ? D ++ BlankClip(D, LongestClip-Framecount(D)) : D
#Mix Audio
Sound = (AudioMix) ? MergeChannels(MixAudio(ConvertToMono(A).Amplify(0.49), ConvertToMono(C).Amplify(0.49)), MixAudio(ConvertToMono(B).Amplify(0.49), ConvertToMono(D).Amplify(0.49))):
\ MergeChannels(GetLeftChannel(A), GetRightChannel(A), GetLeftChannel(B), GetRightChannel(B), GetLeftChannel(C), GetRightChannel(C), GetLeftChannel(D), GetRightChannel(D))
AudioDub(last, Sound)
}
|