# SimpleSlugUpscale v0.9 # # This script is designed to simplify the process of cropping and scaling a clip from one arbitrary size to # another, providing presets that cover several commonly used frame sizes, but also allowing for custom output # dimensions and pixel/display aspect ratios. Feel free to contact me with questions or comments, either by # email at robert.martens@gmail.com or on Twitter @ItEndsWithTens # # Requirements # # AviSynth 2.5.x (I've tested this script in SEt's 2.5.8MT, and vanilla 2.5.8, 2.5.7, and 2.5.6) # TempGaussMC_beta2 (by default; other versions, and other bob deinterlacers, are also supported) # MaskTools v2 # MVTools 2 # NNEDI2 # RemoveGrain & Repair 1.0 prerelease (mode 20, used by TGMCb2, only introduced in this version) # VerticalCleaner # # These can be found with a quick search online, or you can head to http://www.gyroshot.com/simpleslug.htm # to find copies I've hosted for the sake of convenience. Full source code is available for everything but # NNEDI2, which hasn't seen a public source release as of this writing. You can use whichever bob deinterlacer # you prefer, but if it's not TGMC beta 2 you'll need to look elsewhere for the necessary plugins. # # Basic use # # I know this much documentation can be overwhelming, but there are only three things you need to know to make # this script do something useful: # # 1.) Is your input progressive? If so, set prog=true and ignore the rest of this paragraph. For interlaced # footage, ensure that it's in the proper colorspace for whichever deinterlacer you plan to use. By # default, I employ TempGaussMC_beta2, which demands YV12, so either use pixel_type="YV12" in your # source filter, or add ConvertToYV12(interlaced=true) to your script before the call to SimpleSlug. # # 2.) Is your input anamorphic? This only applies to widescreen NTSC DV, widescreen PAL DV, and 1440x1080 # HD clips with a display aspect of 16:9 (including the HDV2 and HDCAM formats). If yours is among # those, set widein=true, otherwise leave the argument out. If you have anamorphic footage that's not # one of the three listed formats, you'll need to leave this option turned off and use PARin to define # the pixel aspect by hand. # # 3.) What size output do you want? There are facilities present to generate custom output sizes, but in # most cases you'll want to use the 'size' parameter with one of the presets defined in this table: # # name size PAR interlaced? # deint same as input same no # 480sq 640x480 1:1 no # 360sq 640x360 1:1 no # DVfullpNTSC 720x480 10:11 no # DVfulliNTSC 720x480 10:11 bottom field first # DVfullpPAL 720x576 59:54 no # DVfulliPAL 720x576` 59:54 bottom field first # DVwidepNTSC 720x480 40:33 no # DVwideiNTSC 720x480 40:33 bottom field first # DVwidepPAL 720x576 118:81 no # DVwideiPAL 720x576 118:81 bottom field first # 720p 1280x720 1:1 no # 1080psq 1920x1080 1:1 no # 1080isq 1920x1080 1:1 top field first # 1080pana 1440x1080 4:3 no # 1080iana 1440x1080 4:3 top field first # # Stick "box" or "boxbg" on to the end of any of those names to trigger automatic letter/pillar boxes, # that use either a solid color or a blurred version of the input clip as their bars, respectively. # # To demonstrate, assuming you have progressive, anamorphic input, and you want square pixel 1080p output # that's padded with a Gaussian blurred copy of the input, your call to SimpleSlug would look like this: # # SimpleSlugUpscale(prog=true,widein=true,size="1080psqboxbg") # # Parameters # # prog bool, default false # # Lets you process progressive footage, bypassing the deinterlacing procedure. # # widein bool, default false # # Allows anamorphic widescreen input; only covers DV NTSC wide (40:33 PAR), DV PAL wide (118:81 PAR), and # anamorphic 1080 HD (4:3 PAR). For other anamorphic input, leave this set to false and specify a custom pixel # aspect with PARin. # # PARin float # # Sets pixel aspect ratio of input clip. Presets account for the most common types of input, but you can # specify your own if you like. Enter the value as either a float or a formula (i.e. 1.333333 or 4.0/3.0). # # drate bool, default false # # For progressive output from interlaced input, this gives 60p for NTSC, 50p for PAL. No effect on interlaced # output. Mutually exclusive with shtrhack. # # shtrhack bool, default false # # Throws an exception if both it and drate are true (an unnecessary combo, therefore probably an oversight by # the user), and has no effect on interlaced output, but for same rate progressive output false will simply # select every other frame of the deinterlacer's output, while true will blend every pair of frames together. # The end result being that false gives you output that's 30p with a 1/60th shutter (NTSC) or 25p with a 1/50th # shutter (PAL), and true simulates the look of 30p with a 1/30th shutter (NTSC) or 25p with a 1/25th shutter # (PAL). It's a cheap hack, as per the name, so don't stake your reputation on its results. # # hshift, vshift int, default 0 # # With some combinations of output settings, input video will be cropped as necessary to fit the shape of the # output frame. These two parameters let you reframe your video, if for example a subject's head has been cut # off by the default position of the crop area. Please note that these act as offsets for said crop area, and # are relative to 0. Use negative numbers to shift the video down and to the right, positive numbers to bring # it up and left. Should you enter too large a value, an error message will pop up and present you with the # maximum for your particular combination of input clip and output size. # # boxcolor int, default color_black # # Determines color of pillarbox or letterbox bars. See your AviSynth plugins directory for colors_rgb.avsi, # which lists a series of global variables that correspond to commonly used colors. If you want a color not # defined there, see the "Colors" section of the AviSynth documentation for more info on defining RGB values. # # boxbgblur float, 1.0 through 100.0, default 2.0 # # For "bg" size options, sets blur for background video. Blur is achieved by GaussResize, this value sets 'p', # so lower numbers blur more. # # qual string, "dumbbob", "low", "balance", or custom string, default "balance" # # Sets quality of deinterlacing. Any bob deinterlacer will work, but presets use TempGaussMC_beta2. "dumbbob" # is the default for downconversions where the output height is 1.5 times or more smaller than the input # height. "balance" is a compromise between speed and quality, and is default for everything else. "low" is # another preset I've made available, and though the tendency toward aliasing makes me uncomfortable using it # for anything by default, you may wish to try it out; it's noticeably faster than "balance", and the slight # quality drop may be worth it for the extra speed. # # You can also enter a custom string here to run any bob deinterlacer you like with whatever arguments you see # fit. The string must be the call to the deinterlacer function, so if, for example, you wanted to use # LeakKernelBob, you would use qual="LeakKernelBob(order=1)". If you have a need to, you can also string # multiple filters together here. qual="TempGaussMC_alpha3().Invert()", for example. How useful that will prove # to most people, I'm not sure, but the option is there. The full gamut of possibilities is too great to cover # here, but if you want custom settings you know what you're doing. Don't forget to surround your qual string # with triple quotes if said string contains its own quotes! # # resize string, default "BlackmanResize" for upscaling in AviSynth 2.5.8, "Lanczos4Resize" for upscaling in # earlier versions, "BilinearResize" for downscaling # # Allows for change of scaling technique; argument must be the name of the resizer. See the AviSynth manual for # all possible values (Core filters->Geometric deformation filters->BilinearResize / etcetera). # # ep0, ep1 string # # These let you specify extra parameters for the resizer; b and c for Bicubic, taps for Blackman and Lanczos, # and p for Gauss. You must type the entire assignment, mind you: ep0="b=0.0",ep1="c=1.0" # # size string, default "720p" # # Determines output size. Anything above 720p is really pushing it with DV source, I don't recommend larger # frames unless you're desperate. The method used to parse this variable provides some flexibility in how you # type the string, but I recommend choosing from the names I use in the table shown at the top of this script. # Add "box" or "boxbg" to the end of any name to trigger pillar or letterboxed output; the entire area of the # input frame will be retained and padded either horizontally or vertically to fit the shape of the output. Box # will simply use a solid color, set by 'boxcolor', while bg will use a cropped, blurred version of the input, # whose blur can be adjusted with 'boxbgblur'. # # outwidth, outheight float # # If you desire a custom output frame size, use these parameters to set it. Odd values can be used only with # RGB video. Output dimensions in all cases, preset or custom, will be rounded to the closest multiple of modw # and modh. If you have RGB video, and you want to use an odd number for one of the axes, you'll need to set # 'modw' or 'modh' (or both) as appropriate. See below for details. # # PARout float # # Sets pixel aspect for output. Uses the same presets as PARin, so if you want a custom output PAR, use this # to define it. # # modw, modh float, default 1.0 for size "deint", modw 16.0 and modh 8.0 for 360sq and all 1080 "size" presets, # 16.0 otherwise # # Allows for easier codec-friendly output sizing. All output dimensions respect this, so frame size and box # edges all land on multiples of modw and modh. The resulting aspect ratios will therefore be slightly # different than what you ask for, but they'll be close enough that you likely won't notice. Hopefully the # improvement in compression efficiency will make up for that. Of course, you can change these values as you # see fit, so if you know what you're doing go right ahead. # # DARout float, default same as input unless custom outwidth and outheight are both requested # # If you want a custom output display aspect, define it here. For example, if you want output that's 640 pixels # wide, and has a display aspect of 2.35, but you don't know the vertical dimension, use DARout=2.35 along with # outwidth=640 to have SimpleSlug auto-calculate an appropriate height. # # boxvideoDAR float, default same as input DAR # # Only for "box" and "boxbg" sizes, this lets you set the display aspect of the video frame as distinct from # the display aspect of the overall frame. By default the entire area of the input clip is retained, and simply # padded to match the desired output DAR. If you want your input cropped to a certain aspect, however, you can # define it here. # # boxshifth, boxshiftv int, default 0 # # In addition to shifting the crop area with hshift and vshift, you can slide your video frame up and down (for # letterboxed output) or left and right (for pillarboxed output) within the output frame. Maximum values for # the given combination of input and output will be presented in an error message should you exceed them. # # Changes # 0.9 - July 20th, 2010 - Added DARout parameter, and associated logic, to allow auto generation of custom # output dimensions when only some information is known, added boxvideoDAR to let users # change shape of center section in "box" or "boxbg" modes, added boxshifth and # boxshiftv for shifting center frame up and down or back and forth within overall # frame, changed modw default to 16.0, changed modh default to 8.0 for "360sq" and all # 1080 presets, 16.0 for everything else, simplified qual logic, redesigned resize # condition to allow for older versions of AviSynth, removed two Asserts (unnecessary # since hshift and vshift are silently rounded to mod 4 and 2, respectively), removed # final BilinearResize in Box function as new design generates proper sizes without it, # changed boxbgblur to float, wrapped outwidth, outheight, modw and modh in Float # function (not strictly required, but I feel safer explicitly casting my variables), # changed gausswidth in Box function to derive from outwidth instead of inwidthf, # removed unnecessary Round of outwidth and outheight after crop argument calculation # in main function, removed redundant "return" statement for both functions, passed # inwidthf and inheightf straight into Box function from main instead of recalculating # them, removed several unnecessary order-of-operations parentheses throughout script, # added extra conditions to 'outwidth' check to improve reliability. # # 0.8 - 0.1 - See http://www.gyroshot.com/simpleslug.htm for full changelog. function SimpleSlugUpscale( clip orig, bool "prog", bool "widein", float "PARin", bool "drate", bool "shtrhack", \ int "hshift", int "vshift", int "boxcolor", float "boxbgblur", string "qual", \ string "resize", string "ep0", string "ep1", string "size", float "outwidth", \ float "outheight", float "PARout", float "modw", float "modh", float "DARout", \ float "boxvideoDAR", int "boxshifth", int "boxshiftv") { prog = Default(prog, false) widein = Default(widein, false) drate = Default(drate, false) shtrhack = Default(shtrhack, false) boxcolor = Default(boxcolor, color_black) size = Default(size, Defined(outwidth) || Defined(outheight) ? "" : "720p") modw = Float(Default(modw, size=="deint" ? 1.0 : 16.0)) modh = Float(Default(modh, size=="deint" ? 1.0 : FindStr(size,"360")>0||FindStr(size,"1080")>0 ? 8.0 : 16.0)) Assert(!(drate==true && shtrhack==true), \ "SimpleSlugUpscale: No reason for both drate and shtrhack to be true! Please check your arguments.") inwidthf = Float(orig.Width()) inheightf= Float(orig.Height()) outwidth = Float(Default(outwidth, \ size=="deint" ? inwidthf : \ (FindStr(size,"480") > 0||FindStr(size,"360") > 0)&&FindStr(size,"sq") > 0 ? \ 640.0 : \ FindStr(size,"720") > 0 ? 1280.0 : \ FindStr(size,"1080") > 0 && FindStr(size,"sq") > 0 ? 1920.0 : \ FindStr(size,"1080") > 0 && FindStr(size,"ana") > 0 ? 1440.0 : \ FindStr(size,"DV") > 0 ? 720.0 : 0.0)) outheight = Float(Default(outheight, \ size=="deint" ? inheightf : \ FindStr(size,"480sq") > 0 ? 480.0 : \ FindStr(size,"360sq") > 0 ? 360.0 : \ FindStr(size,"DV") > 0 ? FindStr(size,"PAL") > 0 ? 576.0 : 480.0 : \ FindStr(size,"720") > 0 ? 720.0 : \ FindStr(size,"1080") > 0 ? 1080.0 : 0.0)) PARin = Default(PARin, widein==true ? inheightf==576.0 ? 118.0/81.0 : \ inheightf==480.0 ? 40.0/33.0 : \ 4.0/3.0 : \ inheightf==576.0 && (inwidthf==720.0||inwidthf==704.0) ? 59.0/54.0 : \ inheightf==480.0 && (inwidthf==720.0||inwidthf==704.0) ? 10.0/11.0 : 1.0) PARout = Default(PARout, size=="deint" ? PARin : \ LeftStr(size,6)=="DVwide" ? FindStr(size,"PAL")>0? 118.0/81.0 : \ 40.0/33.0 : \ LeftStr(size,6)=="DVfull" ? FindStr(size,"PAL")>0? 59.0/54.0 : \ 10.0/11.0 : \ FindStr(size,"ana") > 0 ? 4.0/3.0 : \ Defined(DARout)&&outwidth!=0.0&&outheight!=0.0 ? \ DARout / (outwidth / outheight) : 1.0) DARin = inwidthf * PARin / inheightf DARout = Default(DARout, outwidth!=0.0&&outheight!=0.0 ? outwidth * PARout / outheight : \ DARin) outwidth = outwidth==0.0 ? outheight * DARout / PARout : outwidth outheight = outheight==0.0 ? outwidth * PARout / DARout : outheight outwidth = Round(outwidth / modw) * modw outheight = Round(outheight / modh) * modh boxbgblur = Default(boxbgblur, 2.0) qual = Default(qual, inheightf / outheight >= 1.5 || inheightf >= 1080.0 ? "dumbbob" : "balance") resize = Default(resize, outheight <= inheightf ? "BilinearResize" : \ VersionNumber() >= 2.58 ? "BlackmanResize" : "Lanczos4Resize") #### actualDARout = outwidth * PARout / outheight fromheight = actualDARout < DARin ? true : false cropwidth = fromheight ? inheightf * actualDARout / PARin : inwidthf cropheight = fromheight ? inheightf : inwidthf * PARin / actualDARout cropleft = (orig.Width() - cropwidth) / 2 croptop = (orig.Height() - cropheight) / 2 hshift = Default(hshift, 0) vshift = Default(vshift, 0) hshift = orig.IsRGB() ? hshift : Round(hshift / 4.0) * 4 vshift = orig.IsRGB() ? vshift : Round(vshift / 2.0) * 2 hshiftmax = Floor(((orig.Width() - cropwidth) / 2) / modw) * Int(modw) vshiftmax = Floor(((orig.Height() - cropheight) / 2) / modh) * Int(modh) FindStr(size,"box")>0 || FindStr(size,"bg")>0 ? NOP() : \ Eval(""" Assert(Abs(hshift) <= hshiftmax, \ "SimpleSlugUpscale: For this source, 'hshift' must not exceed +/- " + String(hshiftmax) + "!") """) FindStr(size,"box")>0 || FindStr(size,"bg")>0 ? NOP() : \ Eval(""" Assert(Abs(vshift) <= vshiftmax, \ "SimpleSlugUpscale: For this source, 'vshift' must not exceed +/- " + String(vshiftmax) + "!") """) cropleft = (orig.IsRGB() ? Round(cropleft) : (Round(cropleft/4.0) * 4)) + hshift cropwidth = orig.IsRGB() ? Round(cropwidth) : Round(cropwidth/4.0) * 4 cropheight = orig.IsRGB() ? Round(cropheight) : Round(cropheight/2.0) * 2 croptop = (orig.IsRGB() ? Round(croptop) : (Round(croptop/2.0) * 2)) + vshift #### deintcall = qual=="dumbbob" ? \ "Bob()" : \ qual=="low" ? \ """TempGaussMC_beta2(1,1,0,0,0,0,EdiMode="bob",sharpness=0.0,Smode=0,SLmode=0,Sbb=0,SVthin=0.0)""" : \ qual=="balance" ? \ """TempGaussMC_beta2(1,1,3,0,0,0,EdiMode="nnedi2")""" : \ qual bobbed = prog==true ? orig : Eval("orig." + deintcall) shtrclp = drate==true||FindStr(size,"1080i")>0||(LeftStr(size,2)=="DV"&&MidStr(size,7,1)=="i")||prog==true ? \ bobbed : \ drate==false && shtrhack==true ? \ Merge(bobbed.SelectEven(),bobbed.SelectOdd()) : \ bobbed.SelectEven() scaled = FindStr(size,"box") > 0 || FindStr(size,"bg") > 0 ? \ shtrclp.SimpleSlugBox( PARin,boxcolor,boxbgblur,resize,ep0,ep1,size,outwidth,outheight, \ PARout,modw,modh,DARout,boxvideoDAR,hshift,vshift,boxshifth,boxshiftv, \ inwidthf,inheightf,DARin,DARout) : \ Eval("shtrclp." + resize + \ "(Int(outwidth),Int(outheight),src_left=cropleft,src_top=croptop,src_width=cropwidth,src_height=cropheight" + \ (Defined(ep0) ? "," + ep0 : "") + (Defined(ep1) ? "," + ep1 + ")" : ")") ) FindStr(size,"1080i") > 0 ? \ scaled.AssumeTFF().SeparateFields().SelectEvery(4,0,3).Weave() : \ LeftStr(size,2)=="DV" && MidStr(size,7,1)=="i" ? \ scaled.AssumeBFF().SeparateFields().SelectEvery(4,0,3).Weave() : \ scaled } function SimpleSlugBox( clip shtrclp, float "PARin", int "boxcolor", float "boxbgblur", string "resize", string "ep0", \ string "ep1", string "size", float "outwidth", float "outheight", float "PARout", float "modw", \ float "modh", float "DARout", float "boxvideoDAR", int "hshift", int "vshift", int "boxshifth", \ int "boxshiftv", float "inwidthf", float "inheightf", float "DARin", float "DARout") { boxvideoDAR = Float(Default(boxvideoDAR, DARin)) boxshifth = Default(boxshifth, 0) boxshiftv = Default(boxshiftv, 0) boxshifth = Int(Round(Float(boxshifth) / modw) * modw) boxshiftv = Int(Round(Float(boxshiftv) / modh) * modh) #### ctrwidth = DARout > boxvideoDAR ? outheight * boxvideoDAR / PARout : outwidth ctrheight = DARout > boxvideoDAR ? outheight : outwidth * PARout / boxvideoDAR boxlr = (outwidth - ctrwidth) / 2.0 boxtb = (outheight - ctrheight) / 2.0 boxlr = Int(Round(boxlr / modw) * modw) boxtb = Int(Round(boxtb / modh) * modh) ctrwidth = outwidth - (boxlr * 2.0) ctrheight = outheight - (boxtb * 2.0) ctrwidth = Round(ctrwidth / modw) * modw ctrheight = Round(ctrheight / modh) * modh actualvideoDAR =ctrwidth * PARout / ctrheight #### fromheight = actualvideoDAR < DARin ? true : false incropw = fromheight ? inheightf * actualvideoDAR / PARin : inwidthf incroph = fromheight ? inheightf : inwidthf * PARin / actualvideoDAR incropw = shtrclp.IsRGB() ? incropw : Round(incropw / 4.0) * 4 incroph = shtrclp.IsRGB() ? incroph : Round(incroph / 2.0) * 2 incropl = fromheight ? (shtrclp.Width() - incropw) / 2 : 0 incropt = fromheight ? 0 : (shtrclp.Height() - incroph) / 2 incropl = (shtrclp.IsRGB() ? incropl : Round(incropl / 4.0) * 4) + hshift incropt = (shtrclp.IsRGB() ? incropt : Round(incropt / 2.0) * 2) + vshift hshiftmax = Int(Floor(((shtrclp.Width() - incropw) / 2) / modw) * modw) vshiftmax = Int(Floor(((shtrclp.Height() - incroph) / 2) / modh) * modh) Eval(""" Assert(Abs(hshift) <= hshiftmax, \ "SimpleSlugUpscale: For this source, 'hshift' must not exceed +/- " + String(hshiftmax) + "!") """) Eval(""" Assert(Abs(vshift) <= vshiftmax, \ "SimpleSlugUpscale: For this source, 'vshift' must not exceed +/- " + String(vshiftmax) + "!") """) Eval(""" Assert(Abs(boxshifth) <= boxlr, \ "SimpleSlugUpscale: For this output, 'boxshifth' must not exceed +/- " + String(boxlr) + "!") """) Eval(""" Assert(Abs(boxshiftv) <= boxtb, \ "SimpleSlugUpscale: For this output, 'boxshiftv' must not exceed +/- " + String(boxtb) + "!") """) center = Eval("shtrclp." + resize + \ "(Round(ctrwidth),Round(ctrheight),src_left=incropl,src_top=incropt,src_width=incropw,src_height=incroph" + \ (Defined(ep0) ? "," + ep0 : "") + (Defined(ep1) ? "," + ep1 + ")" : ")") ) #### bgwidth = Int(outwidth) bgheight = Int(outheight) bgcropwidth = Round(DARout > boxvideoDAR ? ctrwidth : ctrheight * DARout / PARout) bgcropheight = Round(DARout > boxvideoDAR ? bgcropwidth * PARout / DARout : ctrheight) bgcropleft = Round((ctrwidth - bgcropwidth) / 2.0) bgcroptop = Round((ctrheight - bgcropheight) / 2.0) bgcropleft = Round(bgcropleft / 4.0) * 4 bgcropwidth = Round(bgcropwidth / 4.0) * 4 bgcropheight = Round(bgcropheight / 2.0) * 2 bgcroptop = Round(bgcroptop / 2.0) * 2 gausswidth = Round(outwidth / 4.0) gaussheight = Round(gausswidth * PARout / DARout) gausswidth = Round(gausswidth / 4.0) * 4 gaussheight = Round(gaussheight / 2.0) * 2 bg = center.GaussResize(gausswidth,gaussheight,bgcropleft,bgcroptop,bgcropwidth,bgcropheight,boxbgblur) \ .BilinearResize(bgwidth,bgheight) #### boxlr==0&&boxtb==0 ? center : \ FindStr(size,"bg")==0 ? \ center.AddBorders(boxlr+boxshifth,boxtb+boxshiftv,boxlr-boxshifth,boxtb-boxshiftv,boxcolor) : \ DARout > boxvideoDAR ? \ Eval("StackHorizontal(" + \ (boxlr+boxshifth==0 ? "" : "bg.Crop(0,0,boxlr+boxshifth,bgheight),") + \ "center" + \ (boxlr-boxshifth==0 ? "" : ",bg.Crop(bgwidth-(boxlr-boxshifth),0,boxlr-boxshifth,bgheight)") + ")" \ ) : \ Eval("StackVertical(" + \ (boxtb+boxshiftv==0 ? "" : "bg.Crop(0,0,bgwidth,boxtb+boxshiftv),") + \ "center" + \ (boxtb-boxshiftv==0 ? "" : ",bg.Crop(0,bgheight-(boxtb-boxshiftv),bgwidth,boxtb-boxshiftv)") + ")" \ ) }