# KenBurnsEffect() - June 12st, 2008 # Given a clip, Zooms, Pans & Rotates Clip with the Ken Burns Effect. # # Requirements: # zoom.dll # http://forum.doom9.org/showthread.php?t=49429 -Original zoom thread # http://avisynth.org/warpenterprises/files/zoom_25_dll_20050122.zip -Direct Download # CalcBox(), ZoomBoxIt() # http://forum.doom9.org/showthread.php?p=1111789#post1111789 # # Inputs: # clip c: input clip, needs to be RGB32() if useZoomBox = 0 or 1 # Optional Parameters: ## ## # Mode 2 - Starting Alignment: # int startAlign: -9 to +9 (0=Do not use Align). Positive values - fit with no black borders, may crop clip. Negative values - fit with black borders, may letterbox clip. # 1:top left. 2:top center. 3:top right. # 4:middle left. 5:middle center. 6:middle bottom. # 7:bottom left. 8:bottom center. 9:bottom right. # # Mode 1 - Starting Box: # float startX1: upper left x cord # float startY1: upper left y cord # float startX2: lower right x cord # float startY2: lower right y cord # 3 or 4 out of 4 points must be defined when using Mode 1 # when omitting a single point, it will calculate the missing value, with the Aspect Ratio in mind. # # float startZoomFactor: 100 = 100%, ect... # Negative values is the zoom of the pixels, positive values is the zoom of the frame. # When converting AR, this isn't perfect. # float startPanX: shift the clip x pixels. Value in source pixels. - left, + right # float startPanY: shift the clip x pixels. Value in source pixels. - up, + down # float startAngle: Rotate clip so many degrees. Positive is Clockwise. ## ## # ## ## # Mode 2 - Ending Alignment: # int endAlign: -9 to +9 (0=Do not use Align). Positive values - fit with no black borders, may crop clip. Negative values - fit with black borders, may letterbox clip. # 1:top left. 2:top center. 3:top right. # 4:middle left. 5:middle center. 6:middle bottom. # 7:bottom left. 8:bottom center. 9:bottom right. # # Mode 1 - Ending Box: # float endX1: upper left x cord # float endY1: upper left y cord # float endX2: lower right x cord # float endY2: lower right y cord # 3 or 4 out of 4 points must be defined when using Mode 1 # when omitting a single point, it will calculate the missing value, with the Aspect Ratio in mind. # # float endZoomFactor: 100 = 100%, ect... # Negative values is the zoom of the pixels, positive values is the zoom of the frame. # When converting AR, this isn't perfect. # float endPanX: shift the clip x pixels. Value in source pixels. - left, + right # float endPanY: shift the clip x pixels. Value in source pixels. - up, + down # float endAngle: Rotate clip so many degrees. Positive is Clockwise. ## ## # # int width: Output Width # int height: Output Height # int startFrame: starting frame of pan and zoom # int endFrame: ending frame of pan and zoom # string ResizeMethod: name of resize function. Default = BilinearResize # float SourceDAR: Display Aspect Ratio of the Source. If 0 then it uses the source aspect ratio. # float TargetDAR: Display Aspect Ratio of the Target. Usefull for DVD's. If 0 then it uses the source aspect ratio. # # int useZoomBox: 0 - Never, 1 - for static parts, 2 - for everything. default 2 # float Speed: 1 is "normal". For high quality set to something like 0.25. For speed set to 5+. Relevant if useZoomBox=0 or 1. # int cubic: Type of zoom, pan & rotate. # int cubicX: Type of pan in the x direction. # int cubicY: Type of pan in the y direction. # int cubicA: Type of rotation. # int cubicZ: Type of zoom. # int color: Color of letterbox border. Default: $000000 (Black). Irrelevant if useZoomBox=0 or 1. # # # Notes: # Clip should be deinterlaced for best visual quality. # Aspect ratio for output and box(x1,y1,x2,y2) should be the same, unless you want to distort the clip. # The aspect ratio for the 2 boxes as well as the output should to be the same. # Default behavor is to center clip by adding borders (Align=-5). # If you specify Align (Mode 2) and x1,y1,x2,y2 (Mode 1), Mode 1 will be used and the align will controll the position of the zoomFactor. # Mode 1 (x1,y1,x2,y2) can take values from a crop opperation. x2 and y2 must be negative though; so if x2 or y2 equals 0, replace 0 with -0.00001. function KenBurnsEffect(clip c, \ int "startAlign", float "startX1", float "startY1", float "startX2", float "startY2", float "startZoomFactor", float "startPanX", float "startPanY", float "startAngle", \ int "endAlign", float "endX1", float "endY1", float "endX2", float "endY2", float "endZoomFactor", float "endPanX", float "endPanY", float "endAngle", \ int "width", int "height", int "StartFrame", int "EndFrame", string "ResizeMethod", float "SourcePAR", float "SourceDAR", float "TargetPAR", float "TargetDAR", \ int "useZoomBox", float "speed", int "cubic", int "cubicX", int "cubicY", int "cubicA", int "cubicZ", int "color") { #Set Defaults startAlign = Default(startAlign, -5) endAlign = Default(endAlign, -5) startZoomFactor = Default(startZoomFactor, 100.0) endZoomFactor = Default(endZoomFactor, 100.0) startPanX = Default(startPanX, 0.0) startPanY = Default(startPanY, 0.0) endPanX = Default(endPanX, 0.0) endPanY = Default(endPanY, 0.0) startAngle = Default(startAngle, 0.0) endAngle = Default(endAngle, 0.0) width = Default(width, c.width()) height = Default(height, c.height()) length = c.Framecount()-1 StartFrame = Default(StartFrame, 0) EndFrame = Default(EndFrame, length) ResizeMethod = Default(ResizeMethod, "BilinearResize") SourceAR = float(c.width())/float(c.height()) TargetAR = float(width)/float(height) useZoomBox = Default(useZoomBox, 2) speed = Default(speed, 1) cubic = Default(cubic, 0) cubicX = Default(cubicX, cubic) cubicY = Default(cubicY, cubic) cubicZ = Default(cubicZ, cubic) cubicA = Default(cubicA, cubic) color = Default(color, $000000) #Calculate Defaults modzoom = Max(Float(c.width())/Float(width),Float(c.height())/Float(height)) startZoomFactor = startZoomFactor<0 ? (abs(startZoomFactor)/100.0)*modzoom : (abs(startZoomFactor)/100.0) endZoomFactor = endZoomFactor<0 ? (abs(endZoomFactor)/100.0)*modzoom : (abs(endZoomFactor)/100.0) #Check For Any Unreasonable Inputs Assert(startZoomFactor<>0, "KenBurnsEffect: startZoomFactor can not be zero.") Assert(endZoomFactor<>0, "KenBurnsEffect: endZoomFactor can not be zero.") Assert((Defined(startX1) && Defined(startY1) && (Defined(startX2) || Defined(startY2))) || !(Defined(startX1) && Defined(startY1) && Defined(startX2) && Defined(startY2)), "KenBurnsEffect: when using Mode 1, you must define startX1,startY1, startX2 and/or startY2") Assert((Defined(endX1) && Defined(endY1) && (Defined(endX2) || Defined(endY2))) || !(Defined(endX1) && Defined(endY1) && Defined(endX2) && Defined(endY2)), "KenBurnsEffect: when using Mode 1, you must define endX1,endY1, endX2 and/or endY2") Assert(startAlign<9 || startAlign>-9, "KenBurnsEffect: startAlign [" + String(startAlign) + "] should be between -9 and 9.") Assert(endAlign<9 || endAlign>-9, "KenBurnsEffect: endAlign [" + String(endAlign) + "] should be between -9 and 9.") Assert(IsRGB32(c) || useZoomBox==2, "KenBurnsEffect: Clip Needs To Be RGB32. Use ConvertToRGB32() or set useZoomBox=2") Assert(!((cubic>0 || cubicX>0 || cubicY>0 || cubicZ>0 || cubicA>0) && useZoomBox==2), "KenBurnsEffect: Can not use the Cubic option when useZoomBox=2. Set useZoomBox to 0 or 1 or don't use cubic.") Assert(endFrame-startFrame<=length, "KenBurnsEffect: Transition length[" + String(endFrame-startFrame) + "] greater then clip lenght[" + String(length) + "]") Assert(startFrame0 && startFrame>0 ? c.Trim(0, -startFrame).ZoomBoxIt(width, height, ResizeMethod, startX1, startY1, startX2, startY2, color) :nop() end = useZoomBox>0 && endFrame0 ? start + cAlt : cAlt cAlt = useZoomBox==2 && endFrame0 ? start + c : c c = useZoomBox<2 && endFrame