View difference between Paste ID: 4q4qj7FD and b1ZDtYhv
SHOW: | | - or go back to the newest paste.
1
##################################################################################################################
2
#
3-
#	High bitdepth tools for Avisynth - GradFun3mod r6 mod 2
3+
#	High bitdepth tools for Avisynth - GradFun3mod r6 mod 3
4
#       based on Dither v1.27.1
5
#	Author: Firesledge, slightly modified by Gebbi
6
#
7
#  What?
8
#       - This is a slightly modified version of the original GradFun3.
9
#       - It combines the usual color banding removal stuff with resizers during the process
10
#         for sexier results (less detail loss, especially for downscales of cartoons).
11
#       - This is a starter script, not everything is covered through parameters. Modify it to your needs.
12
#
13
#	Requirements (in addition to the Dither requirements):
14
#       - AviSynth 2.6.x
15
#       - Debilinear, Debicubic, DebilinearM
16
#       - NNEDI3 + nnedi3_resize16
17
#
18
#  Changes from the original GradFun3:
19
#       - yuv444 = true
20
#         (4:2:0 -> 4:4:4 colorspace conversion, needs 1920x1080 input)
21-
#       - resizer = [ "none", "Debilinear", "DebilinearM", "Debicubic", "DebicubicM", "Spline16",
21+
#       - resizer = [ "none", "Debilinear", "DebilinearMT", "DebilinearM", "DebilinearMTM", "Debicubic", "DebicubicMT", "DebicubicM", "DebicubicMTM", "Spline16",
22-
#         "Spline36", "Spline64", "lineart_rpow2", "lineart_rpow2_bicubic" ] 
22+
#         "Spline36", "Spline64", "lineart_rpow2", "lineart_rpow2_bicubic", "lineart_rpow2MT", "lineart_rpow2_bicubicMT" ] 
23
#         (use it only for downscales)
24
#           NOTE: As of r2 Debicubic doesn't have 16-bit precision, so a Y (luma) plane fix by torch is used here,
25
#                 more info: https://mechaweaponsvidya.wordpress.com/2015/07/07/a-precise-debicubic/
26
#                 Without yuv444=true Dither_resize16 is used with an inverse bicubic kernel.
27
#       - w = 1280, h = 720
28
#         (output width & height for the resizers; or production resolution for resizer="lineart_rpow2")
29
#       - smode = 4
30
#         (the old GradFun3mod behaviour for legacy reasons; based on smode = 1 (dfttest);
31
#         not useful anymore in most cases, use smode = 2 instead (less detail loss))
32
#       - deb = true
33
#         (legacy parameter; same as resizer = "DebilinearM")
34
#
35
#  Usage examples:
36
#       - Source is bilinear 720p->1080p upscale (BD) with 1080p credits overlayed,
37
#         revert the upscale without fucking up the credits:
38
#               lwlibavvideosource("lol.m2ts")
39
#               GradFun3mod(smode=1, yuv444=true, resizer="DebilinearM")
40
#
41
#       - You just want to get rid off the banding without changing the resolution:
42
#               GradFun3(smode=2)
43
#
44
#       - Source is 1080p production (BD), downscale to 720p:
45
#               GradFun3mod(smode=2, yuv444=true, resizer="Spline36")
46
#
47
#       - Source is a HDTV transportstream (or CR or whatever), downscale to 720p:
48
#               GradFun3mod(smode=2, resizer="Spline36")
49
#
50
#       - Source is anime, 720p->1080p upscale, keep the resolution
51
#         but with smoother lineart instead of bilinear upscaled shit:
52
#               GradFun3mod(smode=2, resizer="lineart_rpow2")
53
#         This won't actually resize the video but instead mask the lineart and re-upscale it using
54
#         nnedi3_rpow2 which often results in much better looking lineart (script mostly by Daiz).
55
#
56
#       Note: Those examples don't include parameters like thr, radius, elast, mode, ampo, ampn, staticnoise.
57
#             You probably don't want to use the default values.
58
#             For 16-bit output use:
59
#              GradFun3mod(lsb=true).Dither_out()
60
#
61
#  What's the production resolution of my korean cartoon?
62
#       - Use your eyes combined with Debilinear(1280,720) - if it looks like oversharped shit,
63
#         it was probably produced in a higher resolution.
64
#       - Use Debilinear(1280,720).BilinearResize(1920,1080) for detail loss search.
65
#       - Alternatively you can lookup the (estimated) production resolution at
66
#         http://anibin.blogspot.com  (but don't blindly trust those results)
67
#
68
#	This program is free software. It comes without any warranty, to
69
#	the extent permitted by applicable law. You can redistribute it
70
#	and/or modify it under the terms of the Do What The Fuck You Want
71
#	To Public License, Version 2, as published by Sam Hocevar. See
72
#	http://sam.zoy.org/wtfpl/COPYING for more details.
73
#
74
##################################################################################################################
75
76
77
Function GradFun3mod (clip src, float "thr", int "radius", float "elast",
78
\	int "mask", int "mode", float "ampo", float "ampn", int "pat",
79
\	bool "dyn", float "dthr", int "smode", float "wmin", float "thr_det",
80
\	float "thr_edg", int "debug", int "subspl", bool "lsb", bool "lsb_in",
81
\	bool "staticnoise", float "thrc", int "radiusc", float "elastc",
82
\	int "y", int "u", int "v", clip "ref", bool "slice", bool "yuv444", int "w", int "h", string "resizer", bool "deb")
83
{
84
	thr     = Default (thr,       0.35)
85
	thrc    = Default (thrc,       thr)
86
	radius  = Default (radius,      12)
87
	radiusc = Default (radiusc, radius)
88
	elast   = Default (elast,      3.0)
89
	elastc  = Default (elastc,   elast)
90
	mask    = Default (mask,         2)
91
	smode   = Default (smode,        2)
92
	wmin    = Default (wmin,       1.0)
93
	thr_det = Default (thr_det, 2 + Round (Dither_max (thr - 0.35, 0) / 0.3))
94
	debug   = Default (debug,        0)
95
	subspl  = Default (subspl,       0)
96
	lsb     = Default (lsb,      false)
97
	lsb_in  = Default (lsb_in,   false)
98
	ref     = Default (ref,        src)
99
	yuv444 = Default (yuv444, false)
100
	w = Default (w, 1280)
101
	h = Default (h, 720)
102
	resizer = Default (resizer, "none")
103
	deb = Default (deb, false)
104
	
105
	
106
	# Do lineart smoothing first for sharper results
107
	
108
	ow = src.Width()
109
	oh = src.Height()
110
	
111-
	src = (resizer == "lineart_rpow2") ? lineart_rpow2(src, w, h, ow, oh, false)
111+
	src = (resizer == "lineart_rpow2") ? lineart_rpow2(src, w, h, ow, oh, false, false)
112-
\           : (resizer == "lineart_rpow2_bicubic") ? lineart_rpow2(src, w, h, ow, oh, true)
112+
\           : (resizer == "lineart_rpow2MT") ? lineart_rpow2(src, w, h, ow, oh, true, true)
113
\           : (resizer == "lineart_rpow2_bicubic") ? lineart_rpow2(src, w, h, ow, oh, true, false)
114
\           : (resizer == "lineart_rpow2_bicubicMT") ? lineart_rpow2(src, w, h, ow, oh, true, true)
115
\           : src
116
117
	# Input range check. The other parameters are checked by the plugins.
118
	Assert (radius  > 0, "GradFun3: "+chr(34)+"radius" +chr(34)+" must be strictly positive.")
119
	Assert (radiusc > 0, "GradFun3: "+chr(34)+"radiusc"+chr(34)+" must be strictly positive.")
120
	Assert (thr     > 0, "GradFun3: "+chr(34)+"thr"    +chr(34)+" must be strictly positive.")
121
	Assert (thrc    > 0, "GradFun3: "+chr(34)+"thrc"   +chr(34)+" must be strictly positive.")
122
	Assert (thr_det > 0, "GradFun3: "+chr(34)+"thr_det"+chr(34)+" must be strictly positive.")
123-
	(yuv444 && resizer != "lineart_rpow2" && resizer != "lineart_rpow2_bicubic") ? Assert (w == 1280, "GradFun3mod: Output resolution must be 1280x720 when using 4:4:4 colorspace.") : true
123+
124-
	(yuv444 && resizer != "lineart_rpow2" && resizer != "lineart_rpow2_bicubic") ? Assert (h == 720, "GradFun3mod: Output resolution must be 1280x720 when using 4:4:4 colorspace.") : true
124+
125
	(yuv444 && resizer != "lineart_rpow2" && resizer != "lineart_rpow2_bicubic" && resizer != "lineart_rpow2MT" && resizer != "lineart_rpow2_bicubicMT") ? Assert (w == 1280, "GradFun3mod: Output resolution must be 1280x720 when using 4:4:4 colorspace.") : true
126
	(yuv444 && resizer != "lineart_rpow2" && resizer != "lineart_rpow2_bicubic" && resizer != "lineart_rpow2MT" && resizer != "lineart_rpow2_bicubicMT") ? Assert (h == 720, "GradFun3mod: Output resolution must be 1280x720 when using 4:4:4 colorspace.") : true
127
128
	src_8  = (lsb_in) ? src.DitherPost (mode=-1) : src
129
	src_16 = (lsb_in) ? src : src.Dither_convert_8_to_16 ()
130
	ref_16 = (lsb_in) ? ref : ref.Dither_convert_8_to_16 ()
131
	yv411_flag = src.Dither_isyv411 ()
132
133
	# Main debanding
134
135
	yp     = (! Defined (y) || (y == 3)) ? 3 : 1
136
	up     = (! Defined (u) || (u == 3)) ? 3 : 1
137
	vp     = (! Defined (v) || (v == 3)) ? 3 : 1
138
139
	chroma_flag = (  (thrc != thr || radiusc != radius || elastc != elast)
140
\	               && yp == 3 && (up == 3 || vp == 3))
141
	up2    = (chroma_flag) ? 1 : up
142
	vp2    = (chroma_flag) ? 1 : vp
143
144
	src_16
145
	flt_y  =                 Dither_gf3_smooth_mod (last, src_8, ref_16, smode, radius,  thr,  elast,  lsb_in, wmin, subspl, yp, up2, vp2)
146
	flt_c  = (chroma_flag) ? Dither_gf3_smooth_mod (last, src_8, ref_16, smode, radiusc, thrc, elastc, lsb_in, wmin, subspl, 1,  up,  vp) : flt_y
147
	flt    = (chroma_flag) ? flt_y.MergeChroma (flt_c) : flt_y
148
149
	# Edge/detail mask
150
151
	td_lo  = Dither_max (thr_det * 0.75, 1)
152
	td_hi  = Dither_max (thr_det,        1)
153
	mexpr  = Dither_make_expr_gate (td_lo, td_hi)
154
155
	dmask  = (mask > 0 && yv411_flag) ? src_8.ConvertToY8 ()       : src_8
156
	dmask  = (mask > 0) ? dmask.Dither_build_gf3_range_mask (mask) : dmask
157
	dmask  = (mask > 0) ? dmask.mt_lut (expr=mexpr)                : dmask
158
	dmask  = (mask > 0) ? dmask.Dither_removegrain_emul (22, -1)   : dmask
159
	dmask  = (mask > 1) ? dmask.Dither_removegrain_emul (11, -1)   : dmask
160
	dmask  = (mask > 2) ? dmask.Dither_removegrain_emul (20, -1)   : dmask
161
	dmask  = (mask > 0 && yv411_flag) ? dmask.ConvertToYV411 ()    : dmask
162
163
	res_16 = (mask > 0) ? Dither_merge16_8 (flt, src_16, dmask, luma=true, y=yp, u=up, v=vp) : flt
164
165
	# Resizing / colorspace conversion (GradFun3mod)
166
	
167
	resizer = (deb) ? "DebilinearM" : resizer
168
	resizer = (yuv444 && resizer == "none") ? "Spline36" : resizer
169
	
170
	rkernel = (resizer == "Debilinear" && yuv444) ? res_16.DebilinearY(w,h,lsb_inout=true)
171
\           : (resizer == "Debilinear") ? res_16.Debilinear(w,h,lsb_inout=true)
172
\           : (resizer == "DebilinearMT" && yuv444) ? res_16.ResizeX(w, h, desampling=true, kernel="Bilinear",lsb_in=true,lsb_out=true)
173
\           : (resizer == "DebilinearMT") ? res_16.ResizeX(w, h, desampling=true, kernel="Bilinear",lsb_in=true,lsb_out=true)
174
\           : (resizer == "DebilinearM" && yuv444) ? res_16.DebilinearM(w,h,lsb_inout=true,chroma=false)
175
\           : (resizer == "DebilinearM") ? res_16.DebilinearM(w,h,lsb_inout=true)
176
\           : (resizer == "DebilinearMTM" && yuv444) ? res_16.DebilinearM(w,h,lsb_inout=true,chroma=false, DeResizeMT=true)
177
\           : (resizer == "DebilinearMTM") ? res_16.DebilinearM(w,h,lsb_inout=true, DeResizeMT=true)
178
\           : (resizer == "Debicubic" && yuv444) ? res_16.debicubicy_precise(w,h)
179
\           : (resizer == "Debicubic") ? res_16.Dither_resize16(w,h,kernel="bicubic",invksh=true,fh=1.3,fv=1.3,invkstaps=7)
180
\           : (resizer == "DebicubicMT" && yuv444) ? res_16.debicubicy_precise(w,h, DeResizeMT=true)
181
\           : (resizer == "DebicubicMT") ? res_16.Dither_resize16(w,h,kernel="bicubic",invksh=true,fh=1.3,fv=1.3,invkstaps=7)
182
\           : (resizer == "DebicubicM" && yuv444) ? res_16.DebicubicM_precise16(w,h,chroma=false)
183
\           : (resizer == "DebicubicM") ? res_16.DebicubicM_precise16(w,h)
184
\           : (resizer == "DebicubicMMT" && yuv444) ? res_16.DebicubicM_precise16(w,h,chroma=false, DeResizeMT=true)
185
\           : (resizer == "DebicubicMMT") ? res_16.DebicubicM_precise16(w,h, DeResizeMT=true)
186
\           : (resizer == "Spline16" && yuv444) ? res_16.Dither_resize16(w,h,kernel="spline16",fh=1.2,fv=1.2).ConvertToY8()
187
\           : (resizer == "Spline16") ? res_16.Dither_resize16(w,h,kernel="spline16",fh=1.2,fv=1.2)
188
\           : (resizer == "Spline36" && yuv444) ? res_16.Dither_resize16(w,h,kernel="spline36",fh=1.2,fv=1.2).ConvertToY8()
189
\           : (resizer == "Spline36") ? res_16.Dither_resize16(w,h,kernel="spline36",fh=1.2,fv=1.2)
190
\           : (resizer == "Spline64" && yuv444) ? res_16.Dither_resize16(w,h,kernel="spline64",fh=1.2,fv=1.2).ConvertToY8()
191
\           : (resizer == "Spline64") ? res_16.Dither_resize16(w,h,kernel="spline64",fh=1.2,fv=1.2)
192
\           : ((resizer == "lineart_rpow2" || resizer == "lineart_rpow2_bicubic") && yuv444) ? res_16.Dither_resize16(1280,720,kernel="spline36",fh=1.2,fv=1.2).ConvertToY8()
193
\           : (resizer == "lineart_rpow2" || resizer == "lineart_rpow2_bicubic") ? res_16
194
\           : ((resizer == "lineart_rpow2MT" || resizer == "lineart_rpow2_bicubicMT") && yuv444) ? res_16.Dither_resize16(1280,720,kernel="spline36",fh=1.2,fv=1.2).ConvertToY8()
195
\           : (resizer == "lineart_rpow2MT" || resizer == "lineart_rpow2_bicubicMT") ? res_16
196
\           : (resizer == "none") ? res_16
197
\	         : Assert (false, "GradFun3mod: wrong resizer value.") 
198
199
    ly = rkernel
200
    lu = res_16.utoy8().Dither_resize16(1280, 720, src_left=0.25, kernel="blackman")
201
    lv = res_16.vtoy8().Dither_resize16(1280, 720, src_left=0.25, kernel="blackman")
202
    (yuv444) ? ytouv(lu,lv,ly) : rkernel  
203
	
204
	# Dithering
205
206
	result = (lsb) ? last : last.DitherPost (
207
\		mode=mode, ampo=ampo, ampn=ampn, pat=pat, dyn=dyn,
208
\		prot=false, thr=dthr, staticnoise=staticnoise,
209
\		y=yp, u=up, v=vp, slice=slice
210
\	)
211
	result = (lsb)
212
\		? Dither_switch_planes16 (src_16, result, y=y, u=u, v=v)
213
\		: Dither_switch_planes8  (src_8,  result, y=y, u=u, v=v)
214
215
	(debug == 1       ) ? dmask.GreyScale ()        : result
216
	(debug == 1 && lsb) ? Dither_convert_8_to_16 () : last
217
}
218
219
220
221
Function Dither_gf3_smooth_mod (clip src_16, clip src_8, clip ref_16, int smode, int radius, float thr, float elast, bool lsb_in, float wmin, int subspl, int yp, int up, int vp)
222
{
223
	src_16
224
	  (smode == 0) ? Dither_gf3_smoothgrad_multistage (ref_16, radius, thr, elast, yp, up, vp)
225
\	: (smode == 1) ? Dither_gf3_dfttest (src_8, ref_16, radius, thr, elast, lsb_in, yp, up, vp)
226
\	: (smode == 2) ? Dither_gf3_bilateral_multistage (ref_16, radius, thr, elast, wmin, subspl, yp, up, vp)
227
\	: (smode == 3) ? Dither_gf3_smoothgrad_multistage_3 (radius, thr, elast, yp, up, vp)
228
\  : (smode == 4) ? Dither_gf3_dfttest_mod (src_8, ref_16, radius, thr, elast, lsb_in, yp, up, vp)
229
\	:                Assert (false, "GradFun3mod: wrong smode value.") 
230
}
231
232
233
234
# Valid values for y, u and v: 1 and 3
235
Function Dither_gf3_dfttest_mod (clip src, clip src_8, clip ref,
236
\	int radius, float thr, float elast, bool lsb_in,
237
\	int y, int u, int v)
238
{
239
	Assert (radius <= 128, "GradFun3: max "+chr(34)+"radius" +chr(34)+" value is 128 when smode = 1.")
240
241
	hrad = Dither_max (radius * 3 / 4, 1)
242
243
	(lsb_in) ? src : src_8
244
245-
Function lineart_rpow2 (clip src, int w, int h, int ow, int oh, bool bicubic)
245+
246
\		sigma=thr*12, tbsize=1,
247
\		sbsize=hrad*4, sosize=hrad*3,
248
\		lsb=true, lsb_in=lsb_in,
249
\		Y=(y==3), U=(u==3), V=(v==3)
250
\	)
251
252
	Dither_limit_dif16 (last, ref, thr=thr, elast=elast, y=y, u=u, v=v)
253
}
254-
    (bicubic) ? DebicubicM(src, w, h) : DebilinearM(src, w, h)
254+
255
Function lineart_rpow2 (clip src, int w, int h, int ow, int oh, bool bicubic, bool DeResizeMT)
256
{
257
    w = default(w, 1280)
258
    h = default(h, 720)
259
    ow = default(ow, 1920)
260
    oh = default(oh, 1080)
261-
Function debicubicy_precise(clip src, int dst_width, int dst_height, float "src_left", float "src_top", float "src_width", float "src_height")
261+
262
    DeResizeMT = default(DeResizeMT, false)
263
264
    orig = src
265
    DeResizeMT ? ResizeX(src, w, h, desampling=true, kernel=bicubic ? "Bicubic" : "Bilinear") : (bicubic) ? DebicubicM(src, w, h) : DebilinearM(src, w, h)
266
    nnedi3_rpow2(2, cshift="Spline36Resize", fwidth=ow, fheight=oh)
267
    edges = last.mt_edge("prewitt", 4, 24, 4, 24, chroma="true").removegrain(20, 1)
268
    sharp = last
269
    mt_merge(orig, sharp, edges)
270
}
271
272
Function debicubicy_precise(clip src, int dst_width, int dst_height, float "src_left", float "src_top", float "src_width", float "src_height", bool "DeResizeMT")
273
{
274
    # script by torch
275
    
276
	sw = src.width()
277-
	seed = debicubicy(src, dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, lsb_inout=true)
277+
278
	src_left = default(src_left,   0.0)
279
	src_top = default(src_top,    0.0)
280-
	down = diff.debicubicy(dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, lsb_inout=true)
280+
281
	src_height = default(src_height, sh)
282
	DeResizeMT = default(DeResizeMT, false)
283
	
284
	inv_left = -src_left * dst_width/src_width
285
	inv_top = -src_top * dst_height/src_height
286-
Function DebicubicM_precise16(clip input, int target_width, int target_height, bool "chroma")
286+
287
	inv_height = (sh-src_top) * dst_height/src_height
288
	
289
	seed = DeResizeMT ? ResizeX(src, dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, chroma=false, desampling=true, kernel="Bicubic", lsb_in=true, lsb_out=true) : debicubicy(src, dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, lsb_inout=true)
290
	up = seed.dither_resize16(sw, sh, inv_left, inv_top, inv_width, inv_height, kernel="bicubic", fh=-1.0, fv=-1.0)
291
	diff = dither_sub16(src, up, dif=true).dither_lut16("x 32768 - 99 * 32768 +")
292
	down = DeResizeMT ? diff.ResizeX(dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, chroma=false, desampling=true, kernel="Bicubic", lsb_in=true, lsb_out=true) : diff.debicubicy(dst_width, dst_height, src_left, src_top, src_width+src_left, src_height+src_top, lsb_inout=true)
293
	down = down.dither_lut16("x 32768 - 99 / 32768 + round")
294
	
295
	return seed.dither_add16(down, dif=true)
296
}
297
298
Function DebicubicM_precise16(clip input, int target_width, int target_height, bool "chroma", bool "DeResizeMT")
299
{
300
    # based on DebilinearM v1.3.1
301
    
302
    Assert(target_width  > 0, "GradFun3mod: target width must be greater than 0")
303
    Assert(target_height > 0, "GradFun3mod: target height must be greater than 0")
304
    
305
    thr = 10
306-
         \                 : input.debicubicy_precise(target_width,target_height)
306+
307-
    dbi_8bit = chroma ? input_8bit.Debicubic(target_width,target_height)
307+
308
    kernel = "Spline36"
309
    chroma = Default(chroma, true)
310-
    rs = input.ResizeX(target_width,target_height, kernel=kernel, chroma=chroma, lsb_in=true, lsb=true)
310+
	DeResizeMT = default(DeResizeMT, false)
311
    
312
    w = input.Width()
313
    h = input.Height()/2
314
    uvint = chroma ? 3 : 1
315
    
316
    # Resizing
317
    input_8bit = input.DitherPost(mode=-1)
318
        dbi = chroma ? input.Dither_resize16(target_width,target_height,kernel="bicubic",invksh=true,fh=1.3,fv=1.3,invkstaps=7)
319
         \                 : input.debicubicy_precise(target_width,target_height,DeResizeMT=DeResizeMT)
320
    dbi_8bit = DeResizeMT ? input_8bit.ResizeX(target_width,target_height, chroma=chroma, desampling=true, kernel="Bicubic") : chroma ? input_8bit.Debicubic(target_width,target_height)
321
         \                 : input_8bit.DebicubicY(target_width,target_height)
322
    dbi2     = dbi_8bit.ResizeX(w,h, kernel="Bicubic", chroma=chroma)   
323
    rs = input.ResizeX(target_width,target_height, kernel=kernel, chroma=chroma, lsb_in=true, lsb_out=true)
324
    
325
    # Masking
326
    diffmask = mt_lutxy(input_8bit,dbi2, "x y - abs", U=uvint, V=uvint).mt_binarize(threshold=thr, U=uvint, V=uvint)
327
    diffmask = diffmask.ResizeX(target_width,target_height, kernel="Bilinear", chroma=chroma)
328
    \                                  .mt_binarize(threshold=3, U=uvint, V=uvint)
329
    \                                  .DebilinearM_expand(expand=expand, U=uvint, V=uvint)
330
    \                                  .DebilinearM_inflate(inflate=inflate, U=uvint, V=uvint)
331
    merged = Dither_merge16_8(dbi,rs,diffmask, u=uvint, v=uvint)
332
333
    return merged
334
}