# SimpleSlugUpscale v0.8 # # Simplifies the steps necessary to convert interlaced or progressive video from one arbitrary size and pixel # aspect ratio to another. Presets cover conversions to and from a variety of DV and HD dimensions, with custom # output permitted by 'outwidth', 'outheight', and 'PARout' parameters. SimpleSlug does not currently handle # framerate conversions, so although NTSC<->PAL size changes are not strictly prohibited, you'd do well to seek # proper conversion elsewhere. The same applies to pulldown, which is not accounted for. # # There are many possible combinations of settings for this script, but there are only four things that are # absolutely necessary for it to work. First, if your footage is interlaced, it must be in the proper # colorspace for whatever deinterlacer you'd like to use. By default, I use TempGaussMC, which dictates YV12, # so you'll need to add # # ConvertToYV12(interlaced=true) # # to your script just before the call to SimpleSlugUpscale. Of course, if your codec of choice can decode video # directly to YV12, you can use the 'pixel_type' parameter of AviSynth's source filters to do so, and ignore # the ConvertToYV12 filter. # # Beyond that, you'll only need to know whether or not your clip is progressive, whether it's anamorphic, and # what output size you'd like. You'll describe those properties using the 'prog', 'widein', and 'size' # parameters, respectively. To demonstrate, if you have video that's progressive and anamorphic, and you want # square pixel 1080p output, you'd use this: # # SimpleSlugUpscale(prog=true,widein=true,size="1080psq") # # The full table of preset 'size' options is detailed below. That's all you should need to do for most types of # input, the details are dealt with automatically. If you have more specific requirements, continue reading for # more information, and if you have any questions or comments, don't hesitate to contact me at # robert.martens@gmail.com or get me on Twitter @ItEndsWithTens # # Requirements # # 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. # # # 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 PARout. # # 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 # # Except when using "box" or "boxbg" modes, 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. Maximum is +/- (input width - cropwidth) / 2 for hshift, (input height - cropheight) / 2 for # vshift; 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 int, 1 through 100, default 1 # # For "bg" size options, sets blur for background video. Blur is achieved by GaussResize, this value sets 'p'. # # 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. "low" isn't too bad for 480sq or 360sq modes, runs much faster than balance, and is the default for # all downconversions not covered by dumbbob. "balance" is a compromise between speed and quality, and is # default for straight deinterlacing and any upconversions. A custom string lets you 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, "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 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 # # 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 8 # that's less than or equal to the desired dimension. 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 8.0 # # Allows for easier codec-friendly output sizing. The default is 8.0 instead of 16.0 because of the "360sq" and # 1080 output modes; 360 and 1080 are multiples of 8, but not 16. If you're working with RGB input, and you # want outwidth or outheight to be odd, set modw and/or modh to 1.0 as necessary. # # Changes # 0.8 - May 10, 2010 - Redesigned script to allow arbitrary frame sizes and pixel aspect ratios for both # input and output, restructured deinterlacing process to allow the use of any bob # deinterlacer available for Avisynth, added 'prog' parameter to allow progressive # input to bypass colorspace conversion and deinterlacing, rebuilt pillarbox function # to handle both pillar and letter boxes, added 'ep0' and 'ep1' to allow extra # parameters for whichever resizer is used, added 'PARin' and 'PARout' to facilitate # use of custom pixel aspect ratios, removed 'croptop' parameter and replaced its # functionality with 'vshift', also added 'hshift' to control horizontal offset of # video for certain conversions, added 'boxcolor' to let user define color of # letterbox/pillarbox, added 'boxbgblur' for control over amount of blur used when # generating background video for "boxbg" sizes, added "dumbbob" qual preset, rewrote # error handling for excessive 'vshift' and 'hshift' values (maximum values are now # calculated automatically and presented to the user in the error message), added # 'modw' and 'modh' to adjust output size for more efficient compression, removed # colorspace conversion from script, reinstated 'size' default of "720p", restored some # TGMC defaults for "balance" 'qual' option. # # 0.7 - 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", int "boxbgblur", string "qual", string "resize", \ string "ep0", string "ep1", string "size", float "outwidth", float "outheight", float "PARout", \ float "modw", float "modh") { prog = Default(prog, false) widein = Default(widein, false) drate = Default(drate, false) shtrhack = Default(shtrhack, false) hshift = Default(hshift, 0) vshift = Default(vshift, 0) boxcolor = Default(boxcolor, color_black) boxbgblur = Default(boxbgblur, 1) size = Default(size, "720p") inwidthf = Float(orig.Width()) inheightf= Float(orig.Height()) 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 ? 59.0/54.0 : \ inheightf==480.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 : 1.0) outwidth = Default(outwidth, \ FindStr(size,"480sq") > 0 || FindStr(size,"360sq")>0 ? 640.0 : \ FindStr(size,"720") > 0 ? 1280.0 : \ FindStr(size,"sq") > 0 ? 1920.0 : \ FindStr(size,"ana") > 0 ? 1440.0 : \ FindStr(size,"DV") > 0 ? 720.0 : inwidthf) outheight = Default(outheight, \ 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 : inheightf) modw = Default(modw, 8.0) modh = Default(modh, 8.0) outwidth = Floor(outwidth / modw) * modw outheight = Floor(outheight / modh) * modh qual = Default(qual, inheightf/outheight >= 1.5 ? "dumbbob" : \ outheight < inheightf ? "low" : "balance") resize = Default(resize, outheight <= inheightf ? "BilinearResize" : "BlackmanResize") #### fromheight = (inwidthf*PARin) / inheightf > (outwidth*PARout) / outheight ? true : false cropleft = fromheight==true ? (inwidthf - \ ((inheightf / outheight) * (outwidth*PARout) * (1.0/PARin)) \ ) / 2.0 : 0.0 cropwidth = inwidthf - (cropleft * 2.0) cropheight = fromheight==true ? inheightf : ((cropwidth*PARin) / (outwidth*PARout)) * outheight croptop = (inheightf - cropheight) / 2.0 cropleft = (Round(cropleft/4.0) * 4) + hshift cropwidth = Round(cropwidth/4.0) * 4 cropheight = Round(cropheight/2.0) * 2 croptop = (Round(croptop/2.0) * 2) + vshift outwidth = Round(outwidth) outheight = Round(outheight) #### hshiftmax = orig.IsRGB() ? (orig.Width()-cropwidth)/2 : Floor(((orig.Width()-cropwidth)/2) / 4.0) * 4 vshiftmax = orig.IsRGB() ? (orig.Height()-cropheight)/2 : Floor(((orig.Height-cropheight)/2) / 2.0) * 2 Assert(!(drate==true && shtrhack==true), \ "SimpleSlugUpscale: No reason for both drate and shtrhack to be true! Please check your arguments.") Eval(""" Assert(Abs(hshift) <= hshiftmax, \ "SimpleSlugUpscale: For this source, 'hshift' cannot exceed +/- " + String(hshiftmax) + "!") """) Eval(""" Assert(Abs(vshift) <= vshiftmax, \ "SimpleSlugUpscale: For this source, 'vshift' cannot exceed +/- " + String(vshiftmax) + "!") """) prog==true&&orig.IsRGB()==true ? NOP() : \ Assert(vshift % 2==0, "SimpleSlugUpscale: 'vshift' must be even unless input is RGB!") orig.IsRGB()==true ? NOP() : \ Assert(hshift % 4==0, "SimpleSlugUpscale: 'hshift' must be a multiple of 4 unless input is RGB!") #### 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( prog,PARin,boxcolor,boxbgblur,resize,ep0,ep1,size,outwidth,outheight, \ PARout,modw,modh) : \ Eval("shtrclp." + resize + \ "(outwidth,outheight,src_left=cropleft,src_top=croptop,src_width=cropwidth,src_height=cropheight" + \ (Defined(ep0) ? "," + ep0 : "") + (Defined(ep1) ? "," + ep1 + ")" : ")") ) return 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, bool "prog", float "PARin", int "boxcolor", int "boxbgblur", string "resize", \ string "ep0", string "ep1", string "size", float "outwidth", float "outheight",float "PARout", \ float "modw", float "modh") { inwidthf = Float(shtrclp.Width()) inheightf = Float(shtrclp.Height()) outwidth = Floor(outwidth / modw) * modw outheight = Floor(outheight / modh) * modh pillar = (inwidthf*PARin) / inheightf < (outwidth*PARout) / outheight ? true : false ctrwidth = pillar==true ? (outheight/inheightf) * (inwidthf*PARin) * (1.0/PARout) : outwidth ctrheight = pillar==true ? outheight : ((outwidth*PARout) / (inwidthf*PARin)) * inheightf ctrwidth = shtrclp.IsRGB()==true ? ctrwidth : Round(ctrwidth/4.0) * 4.0 ctrheight = shtrclp.IsRGB()==true ? ctrheight : Round(ctrheight/2.0) * 2.0 boxlr = Round((outwidth - ctrwidth) / 2.0) boxtb = Round((outheight - ctrheight) / 2.0) boxlr = shtrclp.IsRGB()==true ? boxlr : Round(boxlr/4.0) * 4 boxtb = shtrclp.IsRGB()==true ? boxtb : Round(boxtb/2.0) * 2 bgwidth = Round(outwidth) bgheight = Round(outheight) bgcropleft = Round(pillar==true ? 0 : (ctrwidth - \ ((ctrheight/outheight)*outwidth) \ ) / 2.0) bgcropwidth = Round(pillar==true ? ctrwidth : outwidth - (bgcropleft*2.0)) bgcropheight = Round((ctrwidth / outwidth) * ctrheight) bgcroptop = Round((ctrheight - bgcropheight) / 2.0) gausswidth = Round(inwidthf / 4.0) gaussheight = Round((gausswidth / ctrwidth) * ctrheight) gausswidth = Round(Ceil(gausswidth/4.0) * 4.0) gaussheight = Round(Ceil(gaussheight/2.0) * 2.0) center = Eval("shtrclp." + resize + "(Round(ctrwidth),Round(ctrheight)" + \ (Defined(ep0) ? "," + ep0 : "") + (Defined(ep1) ? "," + ep1 + ")" : ")") ) bg = center.GaussResize(gausswidth,gaussheight,bgcropleft,bgcroptop,bgcropwidth,bgcropheight,boxbgblur) \ .BilinearResize(bgwidth,bgheight) return (boxlr==0&&boxtb==0 ? center : \ FindStr(size,"bg")==0 ? \ center.AddBorders(boxlr,boxtb,boxlr,boxtb,boxcolor) : \ pillar==true ? \ StackHorizontal( bg.Crop(0,0,boxlr,bgheight), \ center, \ bg.Crop(bgwidth-boxlr,0,boxlr,bgheight)) : \ StackVertical( bg.Crop(0,0,bgwidth,boxtb), \ center, \ bg.Crop(0,bgheight-boxtb,bgwidth,boxtb))) \ .BilinearResize(Round(outwidth),Round(outheight)) }