Advertisement
Zastin

mt logic for VS

Oct 18th, 2017
436
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.06 KB | None | 0 0
  1. import vapoursynth as vs
  2. import math
  3. from vapoursynth import core
  4. from functools import partial
  5.    
  6. def logic(clipa, clipb=None, mode='and', min=None, max=None, bits=None, flt=None, planes=None):
  7.     """
  8.    mt_logic with some modifications
  9.    
  10.    Changing the output format crashes VS Editor whenever I try it so... buyer beware and all that.
  11.    
  12.    Works on single clips when clipb is an integer, float, or string ('pi', 'e', 'tau')
  13.    
  14.    New parameters 'min' and 'max' can be used to clip the final output
  15.    'max' default to the maximum allowed value when output is an integer format to avoid overflows with depths between 8 and 16
  16.    this isn't strictly necessary, just a safety check since it will crash if you try to preview it
  17.    
  18.    mode='andn' still has its arguments flipped (binary 'clipb and not clipa'), mostly for backward compatibility
  19.    
  20.    ~~~New modes for one or more clips~~~
  21.    dif - return abs(clipa - clipb)
  22.    add/sub/mul/div/pow/root/log -  for simple math operations
  23.    
  24.    ~~~New modes for a single clip only~~~
  25.    sqrt - equal to std.Expr('x 255 / sqrt 255 *')
  26.    sin/cos/tan/asin/acos/atan - for trigonometric approximations
  27.    
  28.    This always uses std.Lut/std.Lut2 so everything is pre-calculated with very high precision
  29.    
  30.    The exact order things happen are as follows, simplified so you can understand it without understanding lookup tables:
  31.    clipb = Depth(clipb, bits=clipa.bits_per_sample)     # no actual processing on the clip
  32.    lut   = mode_function(clipa, clipb)                  # float processing in integer space
  33.    clmp  = clamp(lut, min, max)                         # limit values if specified
  34.    return Depth(clmp, bits=bits, dither_type='none')    # round to target bit depth & sample type
  35.    """
  36.    
  37.     def fill_lut(clipa, clipb, mode, bits, bitsa, bitsb, full, chroma, flt):
  38.        
  39.         scaleo = partial(scalef if full else scalebc if chroma else scaleb, i=bitsa, o=bits, f=flt)
  40.         scaley = partial(scalef if full else scalebc if chroma else scaleb, i=bitsb, o=bitsa, f=False)
  41.         setnumfmt = float if flt else round
  42.         func = get_func(mode, bits, flt)
  43.        
  44.         lut = []
  45.         if isinstance(clipb, vs.VideoNode):
  46.             for y in range(2 ** bitsb):
  47.                 for x in range(2 ** bitsa):
  48.                     lut.append(setnumfmt(clamp_value(scaleo(func(x, scaley(y))), mi, ma)))
  49.         else:
  50.             if isinstance(clipb, str):
  51.                 clipb = clipb.lower()
  52.                 clipb = math.pi if clipb in ('π', 'pi') else e if clipb=='e' else math.tau
  53.             clipb = (1<<bitsa)-1 if mode == 'sqrt' else clipb
  54.             for x in range(2 ** bitsa):
  55.                 lut.append(setnumfmt(clamp_value(scaleo(func(x, clipb)), mi, ma)))
  56.         return lut
  57.        
  58.     f = clipa.format
  59.     bitsa = f.bits_per_sample
  60.     bitsb = None if not isinstance(clipb, vs.VideoNode) else clipb.format.bits_per_sample
  61.     numplanes = f.num_planes
  62.    
  63.     mode = mode.lower()
  64.    
  65.     full = f.color_family in (vs.RGB, vs.YCOCG)
  66.    
  67.     planes = list(range(numplanes)) if planes is None else [planes] if isinstance(planes, int) else planes
  68.    
  69.     bits = bitsa if bits is None else bits
  70.     flt = True if bits==32 else flt if flt is not None else False
  71.    
  72.     mi = min
  73.     ma = max
  74.     if not flt:
  75.         mi = max(mi, 0) if mi is not None else 0
  76.         ma = min(ma, (1<<bits)-1) if ma is not None else (1<<bits)-1
  77.    
  78.     lut = fill_lut(clipa, clipb, mode, bits, bitsa, bitsb, full, False, flt)
  79.     lutc = fill_lut(clipa, clipb, mode, bits, bitsa, bitsb, full, True, flt)
  80.    
  81.     args = dict(bits=bits, floatout=flt)
  82.    
  83.     split = False
  84.     for i in range(len(lut)):
  85.         if lut[i] != lutc[i]:
  86.             split = True
  87.    
  88.     if split and 0 in planes and any_of(planes, '>', 0):
  89.         if isinstance(clipb, vs.VideoNode):
  90.             clipa = core.std.Lut2(clipa, clipb, 0, lut, **args)
  91.             return core.std.Lut2(clipa, clipb, planes.remove(0), lutc, **args)
  92.         else:
  93.             clipa = core.std.Lut(clipa, 0, lut, **args)
  94.             return core.std.Lut(clipa, planes.remove(0), lutc, **args)
  95.     else:
  96.         if isinstance(clipb, vs.VideoNode):
  97.             return core.std.Lut2(clipa, clipb, planes, lut, **args)
  98.         else:
  99.             return core.std.Lut(clipa, planes, lut, **args)
  100.    
  101.    
  102.    
  103. #Internal
  104.  
  105. def clamp_value(val, mi, ma):
  106.     val = max(val, mi) if mi is not None else val
  107.     return min(val, ma) if ma is not None else val
  108.  
  109. def scalef(x, i, o, f):
  110.     x /= (1<<i)-1
  111.     return x if f else x * ((1<<o)-1)
  112.  
  113. def scaleb(x, i, o, f):
  114.     return (x - (1<<(i-4))) / (219<<(i-8)) if f else x * (1<<i) / (1<<o)
  115.  
  116. def scalebc(x, i, o, f):
  117.     return (x - (1<<(i-4))) / (224<<(i-8)) if f else x * (1<<i) / (1<<o)
  118.  
  119.  
  120. def add(x, y): return x + y
  121. def sub(x, y): return x - y
  122. def mul(x, y): return x * y
  123. def div(x, y): return x / y
  124. def root(x, y): return math.pow(x, 1/max(y, 1))
  125. def log(x, y): return math.log(x, y)
  126. def sin(x, y): return math.sin(x)
  127. def cos(x, y): return math.cos(x)
  128. def tan(x, y): return math.tan(x)
  129. def asin(x, y): return math.asin(x)
  130. def acos(x, y): return math.acos(x)
  131. def atan(x, y): return math.atan(x)
  132. def sqrt(x, y, z): return math.sqrt(x / y) if z is None else math.sqrt(x / y) * z
  133. def dif(x, y): return abs(x - y)
  134. def avg(x, y): return (x + y)/2
  135. def get_max(x, y): return max(x, y)
  136. def get_min(x, y): return min(x, y)
  137. def bitwise_and(x, y): return x & y
  138. def bitwise_or(x, y): return x | y
  139. def bitwise_xor(x, y): return x ^ y
  140. def bitwise_andnot(x, y):
  141.     x, y = list(bin(y))[2:], list(bin(x))[2:]
  142.     while len(x) > len(y):
  143.         y.insert(0, '0')
  144.     while len(x) < len(y):
  145.         x.insert(0, '0')
  146.     out = '0b'
  147.     for i in range(len(x)):
  148.         out += '1' if (x[i], y[i]) == ('1', '0') else '0'
  149.     return int(out, base=2)
  150.  
  151. def any_of(arr, mode, val):
  152.     def ts(x, m, y): return x in y if m=='in' else x not in y if mode=='not in' else isinstance(x, y) if mode=='isinstance' else not isinstance(x, y)
  153.     mode = mode.lower()
  154.     if mode in ('isinstance', 'not isinstance', 'in', 'not in'):
  155.         for obj in arr:
  156.             if ts(obj, mode, val):
  157.                 return True
  158.         return False
  159.     else:
  160.         op_table = op_table = {'==': operator.eq, '!=': operator.ne, '>': operator.gt, '<': operator.lt, '>=': operator.ge, '<=': operator.le, 'is': operator.is_, 'is not': operator.is_not}
  161.         return any(map(lambda x: op_table[mode](x, val), arr))
  162.    
  163. def get_func(mode, bits, flt): return {'and': bitwise_and, '&': bitwise_and, 'or': bitwise_or, '|': bitwise_or, 'xor': bitwise_xor, '^': bitwise_xor, 'andn': bitwise_andnot, 'andnot': bitwise_andnot, 'max': get_max, 'min': get_min, 'add': add, '+': add, 'sub': sub, '-': sub, 'mul': mul, '*': mul, 'div': div, '/': div, 'exp': math.pow, 'pow': math.pow, '**': math.pow, 'root': root, 'sin': sin, 'cos': cos, 'tan': tan, 'asin': asin, 'acos': acos, 'atan': atan, 'diff': dif, 'dif': dif, 'abs': dif, 'avg': avg, 'average': avg, 'mean': avg, 'sqrt': partial(sqrt, z=None if flt else (1<<bits)-1)}.get(mode, 'and')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement