Jaded-Encoding-Thaumaturgy / vs-deband

Various debanding tools for VapourSynth
MIT License
15 stars 7 forks source link

Add BreakEdges,AntiMoiree grain postprocess options #92

Closed Setsugennoao closed 3 months ago

Setsugennoao commented 1 year ago

From AVS, asked in #55

function FilmGrainPlus(
    clip a, float  "str", float  "size", float "sharpness",
    float "temp",float  "lo", float  "mid", float "hi",
    string "preset", string "mode", float "preblur",
    val "conv", float  "strc", bool "tv_range", int "show"
) {
    w     = width (a)

    isy   = isy(a)
    bi    = BitsPerComponent(a)
    fs    = propNumElements (a,"_ColorRange")  > 0 ? \
            propGetInt      (a,"_ColorRange") == 0 : false

    szD   = Defined( size      )
    pblD  = Defined( preblur   )

    str   = Default( str      ,       0.2 ,                  )
    sz    = Default( size     ,    w/1920.,                  )
    shrp  = Default( sharpness, szD?-0.87*sz+2:0.93-0.244*str)
    strc  = Default( strc     ,    str*0.5,                  )

    conv  = Default( conv,       false ) # 0.0 - 1.0. Set to true or set strength for the convolution to "break" edges

    pbl   = Default( preblur,     1.0  ) # 0.0 - 2.0. Multiplier for internal blur. Lower or disable by setting it to 0.0 if coming from an upscale for example
    md    = Default( mode,      "gamma") # Add grain in "log", "linear" or "gamma" space

    tv    = Default( tv_range,      !fs)
    ls    = md=="log"
    ln    = md=="linear"

    strc  = strc==-1.0 ? str*0.5 : strc
    ygrey = tv     ? 126 : 128
    rnghlf= ex_bs( ygrey,    8, bi, fulls=false, flt=true)
    MX    = ex_bs(   255,    8, bi, fulls=true,  flt=true)
    rmax  = bi==32 ? "" : bi > 12 ? "range_max /" : string(1./MX)+" *"

    lo    = Default( lo, ls ? 1.5 : ln ? 0.5 : 0.8) # 0.0 - 2.0, non linear strength multiplier for dark  areas
    mi    = Default( mid,ls ? 1.0 : ln ? 1.0 : 1.0) # 0.0 - 2.0, non linear strength multiplier for grey  areas
    hi    = Default( hi, ls ? 0.7 : ln ? 1.2 : 1.0) # 0.0 - 2.0, non linear strength multiplier for light areas

    Chr   = strc > 0.0 && !isy
    Chr32 = Chr ? 3 : 2
    crs   =   ((1-  shrp)     *3)+1
    sz    = max(1.0,4-sz*1.5)
    binom = sqrt(crs)/2.*sqrt(2)

    blk.AddGrainC(str*100*sz, strc*100*sz, constant=false)
    ex_makediff(blk,last,UV=Chr32)

    # Anti-moiree + 'sharpness' support blur
    expr   = binom*(pow(str,0.318)-0.61)*(pow(w/1920.-0.46,0.4)+0.2)*pbl
    pbl    =                        expr > 0.35 ? a.vsTCanny(expr                ,mode=-1,u=Chr32,v=Chr32) : \
             pblD ? sqrt(pbl)/2.*sqrt(2) > 0.35 ? a.vsTCanny(sqrt(pbl)/2.*sqrt(2),mode=-1,u=Chr32,v=Chr32) : a : a

    # 'frei-chen' with 9 and 'conv' for lo and hi respectively
    cn     = isBool(conv) ? conv ? 1-str*0.1 : 1.0 : clamp(1-conv*0.8,0.2,1.0)
    cop    = -0.625*cn + 1.125
    clo    = ex_bs(     9, 8, bi, fulls=true, flt=true)
    chi    = ex_bs(cn*100, 8, bi, fulls=true, flt=true)
    norm   = 1. / (chi    -    clo)

    th1st  = ex_bs(   45,  8, bi, tv_in=true, tv_out=tv)
    th2st  = ex_bs(   85,  8, bi, tv_in=true, tv_out=tv)
    th3st  = ex_bs(  140,  8, bi, tv_in=true, tv_out=tv)
    th4st  = ex_bs(  200,  8, bi, tv_in=true, tv_out=tv)

    th21st = MX / (th2st - th1st)
    th43st = MX / (th3st - th4st)

    SEG    = lo!=1.0 || mi!=1.0 || hi!=1.0

    lop    = bi > 12 ? Format("{lo} * range_max /") : string(lo / MX)+" *"
    mip    = bi > 12 ? Format("{mi} * range_max /") : string(mi / MX)+" *"
    hip    = bi > 12 ? Format("{hi} * range_max /") : string(hi / MX)+" *"
    rh     = string(sqrt((0.501960785-(tv?0.062745098:0))*0.3))

    rngmx  = tv ? "ymax ymin -"  : "range_max"
    srcmx  = tv ? "ymin - "      : ""
    tvout  = tv ? "ymin + "      : ""
    lgnor  = tv ? "2.57 * 1.105" : "2.791 * 1.045"
    linor  = tv ? "0.5023"       : string(0.501960785)

    # Merge 'mode'
    GML = "x "+srcmx+" A@ "+rngmx+" 3 * / sqrt y "+srcmx+rngmx+" 3 * / sqrt + "+rh+" - dup * "+lgnor+" ^ 0 1 clip "+rngmx+" * "
    GMI = "x "+srcmx+" A@ "+rngmx+" / 0 1 clip 2.4 ^ y "+srcmx+rngmx+" / + "+linor+" - 0 1 clip 0.416666667 ^     "+rngmx+" * "
    GMC = "x "+srcmx+" A@ y "+srcmx+" + range_half "+srcmx+" - 0 "+rngmx+" clip "
    GM  = ls ? GML : ln ? GMI : ReplaceStr(GMC,"range_half",Format("{rnghlf}"))

    # 'lo', 'mid' and 'hi' mix
    LMH = Format(" Y@ x dup swap2 - range_max x  {th1st} - {th21st} * -   LO@ "+lop+" 0 1 clip * -
                        dup     Y -           x  {th3st} - {th43st} * neg HI@ "+hip+" 0 1 clip * -
                        dup     Y - range_max  HI LO max  -                   "+mip+" 0 1 clip * -")

    # 'conv' with frei-chen gradient
    EM  = Format(" x[1,1] C@ x[1,-1] H@ + x[-1,1] A@ - x[-1,-1] F@ - x[1,0] x[-1,0] - 1.414213562 * + dup *
                   F H + C - A - x[0,-1] x[0,1] - 1.414213562 * + dup * + sqrt {clo} - {norm} * 0 1 clip {cop} * * - ")

    # Construct expression
    COM = cn<1. ? SEG ? GM+tvout+LMH+" dup Y - "+EM : GM+Format(" dup swap2 - ")+EM+tvout : \
                  SEG ? GM+tvout+LMH                : GM+tvout

    # Expression fit for Chroma
    COC = ReplaceStr(COM," x  "," z ").ReplaceStr("x[", "z[").ReplaceStr(GM,GMC)
    PTW = " dup x - "+(SEG ? "HI" : Format("z {th3st} - {th43st} * neg"))+" "+rmax+" 0 1 clip * -"

    !Chr ? ex_lutxy (pbl,last,                                   COM,        UV=2) : \
           ex_lutxyz(pbl,last,mskY_to_YYY(pbl,luma=true,bits=bi),COM,COC+PTW,UV=3)
}