CODICE
#MaskCL v1.3 by mirkosp
#Mask without the 255 bug and no weird workarounds using opencl.
#Might or might not be faster than dither_merge16 / dither_merge16_8, see if it is for you.
#0 keeps src, 255 keeps overlay, everything else is the intended inbetween (at least it should be).
#Requires tp7's CLExpr: https://github.com/tp7/CLExpr (check "Releases" for download links).
#No error checking so if shit doesn't work as expected blame it on yourself.
#Just supply YUV clips with same colorspace, resolution, framerate, and length to make sure it'll work fine.
#v1.0 and 1.1 were bugged with 16bit because I'm dumb. Like, a lot. YAAAY!
#v1.2 supported yv24 only with luma=true so here goes v1.3.
function MaskCL(clip src, clip overlay, clip mask, int "y", int "u", int "v", bool "luma", bool "lsb_inout", bool "mask8") {
y = Default(y,3)
u = Default(u,2)
v = Default(v,2)
luma = Default(luma,false)
lsb_inout = Default(lsb_inout,false)
mask8 = lsb_inout ? Default(mask8,false) : false
mask = luma ? ytouv(mask,mask,mask) : mask
mask = src.isyv12() ? mask.converttoyv12(matrix="PC.601") : src.isyuy2() ? mask.converttoyuy2(matrix="PC.601") : src.isyv16() ? mask.converttoyv16(matrix="PC.601") : mask
mask = mask8 ? stackvertical(mask,mask) : mask
lsb_inout ? cl_exprxyz(src,overlay,mask,"x 65535 z - * y z * + 65535 /",y=y,u=u,v=v,lsb=true) : cl_exprxyz(src,overlay,mask,"x 255 z - * y z * + 255 /",y=y,u=u,v=v,lsb=false)
}
#HardSub Utilities for Y416 v1.2 by mirkosp
#Y416 is 16bit YUV 4:4:4, by the way. But if you care about this, you likely knew already.
#And of course I mean dithertools' stacked thing, which technically is
#a stacked 8bit thingie. Dem hacks.
#Requires dithertools. Also vsfilter and/or vsfiltermod for the ass support.
#I haven't done extensive testing, so please report any errors you find.
#First and foremost, rgb32 afx clips
#l is the video to overlay on (typically left to last)
#c is the clip to be overlayed
#s is the frame on which to start the overlay
#e is the frame on which to end the overlay
#I'm nice enough to allow the usage of -num_frames style too, tho.
#sm is the colormatrix and tv is a bool for tv range (true) or not (false).
#You should be using dither_convert_rgb_to_yuv's values for sm, but
#uf you're using avisynth's, I'm doing a somewhat rough check myself.
#This also allows me to just call this function later on for ass hardsubbing...
function rgb32ony416(clip l, clip c, int "s", int "e", string "sm", bool "tv") {
assert(c.isrgb32, "dudeplz.")
assert(l.isyv24, "dudeplz.")
assert(l.width == c.width, "check width")
assert(l.height/2 == c.height, "check height")
tv = defined(tv) ? tv : defined(sm) ? sm == "PC.601" ? false : sm == "PC.709" ? false : tv : true
sm = defined(sm) ? sm == "Rec601" ? "601" : sm == "Rec709" ? "709" : sm == "PC.601" ? "601" : sm == "PC.709" ? "709" : sm : (c.width > 1024 || c.height > 600) ? "709" : "601"
s = default(s,0)
e = default(e,0)
s = s+2
l
e = (e > 0) ? e+2 : (e == 0) ? framecount+1 : e
ps = s-1
pe = (e > 0) ? e+1 : s-e
l = l.trim(0,1)+l+l.trim(0,1) #HAX! I don't feel like doing special case checks. Maybe it executes faster this way, too.
l
sa = l.trim(0,ps).converttorgb32()+stackvertical(c.showalpha("rgb32"),c.showalpha("rgb32"))+last.trim(pe,0).converttorgb32()
oc = l.trim(0,ps)+(c.Dither_convert_rgb_to_yuv(output="yv24",matrix=sm,tv_range=tv).dither_convert_8_to_16())+last.trim(pe,0)
saC = sa.Dither_convert_rgb_to_yuv(output="yv24",matrix=sm,tv_range=tv).dither_convert_8_to_16()
l.trim(0,ps)+ytouv(MaskCL(last.utoy(), oc.utoy(), saC), MaskCL(last.vtoy(), oc.vtoy(), saC), MaskCL(last, oc, saC)).trim(s,e)+l.trim(pe,0)
return trim(2,framecount-3) }
#And now for the ass functions
#sm is the colormatrix. If left unspecified, it's autoguessed based on res.
#path is the ass' path, hack is for the bt601 typeset deal.
#If the video you have to overlay on is bt709 and you
#have typeset in bt601 to compensate for the old vsfilter,
#set this to true.
#vfr is the path to the timecodes.
#At the time of the writing, softsubbed 4:4:4 has to be overlayed
#in rgb tho, so it's better to avoid the hack if you're
#dealing with 4:4:4 video, thus I won't account for it by default.
#I'm not 100% sure these work correctly, please report bugs if you encounter them.
function textsubmodony416(clip cs, string path, string "vfr", string "sm", bool "hack") {
hack = default(hack,false)
c = cs.ditherpost(mode=8)
sm = defined(sm) ? sm : (c.width > 1024 || c.height > 600) ? "Rec709" : "Rec601"
bc = blankclip(c,pixel_type="RGB32",color=$FF000000)#pure alpha
crgb = hack ? c.converttorgb32(matrix="Rec601") : c.converttorgb32(matrix=sm)
mergeargb(bc.showalpha(),crgb.showred(),crgb.showgreen(),crgb.showblue())
defined(vfr) ? textsubmod(path,vfr=vfr) : textsubmod(path)
mergeargb(showalpha().invert(),showred(),showgreen(),showblue())
savealpha = last
o = converttoyv24(matrix="Rec601").converttorgb32(matrix="Rec709")
return hack ? rgb32ony416(cs,mergeargb(savealpha.showalpha(),o.showred(),o.showgreen(),o.showblue()),sm=sm) : rgb32ony416(cs,last,sm=sm)
}
function textsubony416(clip cs, string path, string "vfr", string "sm", bool "hack") {
hack = default(hack,false)
c = cs.ditherpost(mode=8)
sm = defined(sm) ? sm : (c.width > 1024 || c.height > 600) ? "Rec709" : "Rec601"
bc = blankclip(c,pixel_type="RGB32",color=$FF000000)#pure alpha
crgb = hack ? c.converttorgb32(matrix="Rec601") : c.converttorgb32(matrix=sm)
mergeargb(bc.showalpha(),crgb.showred(),crgb.showgreen(),crgb.showblue())
defined(vfr) ? textsub(path,vfr=vfr) : textsub(path)
mergeargb(showalpha().invert(),showred(),showgreen(),showblue())
savealpha = last
o = converttoyv24(matrix="Rec601").converttorgb32(matrix="Rec709")
return hack ? rgb32ony416(cs,mergeargb(savealpha.showalpha(),o.showred(),o.showgreen(),o.showblue()),sm=sm) : rgb32ony416(cs,last,sm=sm)
}
#HardSub Utilities for P016 v1.3 by mirkosp
#P016 is 16bit YUV 4:2:0, by the way. But if you care about this, you likely knew already.
#And of course I mean dithertools' stacked thing, which technically is
#a stacked 8bit thingie. Dem hacks.
#Requires dithertools. Also vsfilter and/or vsfiltermod for the ass support.
#I haven't done extensive testing, so please report any errors you find.
#First and foremost, rgb32 afx clips
#l is the video to overlay on (typically left to last)
#c is the clip to be overlayed
#s is the frame on which to start the overlay
#e is the frame on which to end the overlay
#I'm nice enough to allow the usage of -num_frames style too, tho.
#sm is the colormatrix and tv is a bool for tv range (true) or not (false).
#You should be using dither_convert_rgb_to_yuv's values for sm, but
#uf you're using avisynth's, I'm doing a somewhat rough check myself.
#This also allows me to just call this function later on for ass hardsubbing...
function rgb32onp016(clip l, clip c, int "s", int "e", string "sm", bool "tv") {
assert(c.isrgb32, "dudeplz.")
assert(l.isyv12, "dudeplz.")
assert(l.width == c.width, "check width")
assert(l.height/2 == c.height, "check height")
tv = defined(tv) ? tv : defined(sm) ? sm == "PC.601" ? false : sm == "PC.709" ? false : tv : true
sm = defined(sm) ? sm == "Rec601" ? "601" : sm == "Rec709" ? "709" : sm == "PC.601" ? "601" : sm == "PC.709" ? "709" : sm : (c.width > 1024 || c.height > 600) ? "709" : "601"
s = default(s,0)
e = default(e,0)
s = s+2
l
e = (e > 0) ? e+2 : (e == 0) ? framecount+1 : e
ps = s-1
pe = (e > 0) ? e+1 : s-e
l = l.trim(0,1)+l+l.trim(0,1) #HAX! I don't feel like doing special case checks. Maybe it executes faster this way, too.
l
sa = l.trim(0,ps).converttorgb32()+stackvertical(c.showalpha("rgb32"),c.showalpha("rgb32"))+last.trim(pe,0).converttorgb32()
oc = l.trim(0,ps)+(c.Dither_convert_rgb_to_yuv(output="yv12",matrix=sm,tv_range=tv).dither_convert_8_to_16())+last.trim(pe,0)
laC = last.ConvertToYV24().dither_convert_8_to_16()
saC = sa.Dither_convert_rgb_to_yuv(output="yv24",matrix=sm,tv_range=tv, lsb=true).dither_convert_8_to_16()
lC = l.ConvertToYV24().dither_convert_8_to_16()
ocC = oc.ConvertToYV24().dither_convert_8_to_16()
lC.trim(0,ps)+ytouv(MaskCL(laC.utoy(), ocC.utoy(), saC), MaskCL(laC.vtoy(), ocC.vtoy(), saC), MaskCL(laC, ocC, saC)).trim(s,e)+lC.trim(pe,0)
last.DitherPost(mode=8)
return trim(2,framecount-3)
}
#And now for the ass functions
#sm is the colormatrix. If left unspecified, it's autoguessed based on res.
#path is the ass' path, hack is for the bt601 typeset deal.
#If the video you have to overlay on is bt709 and you
#have typeset in bt601 to compensate for the old vsfilter,
#set this to true.
#vfr is the path to the timecodes.
#At the time of the writing, softsubbed 4:2:0 is usually overlayed
#as bt601 due to an old vsfilter bug which is by now standard.
#This means that if you have HD video you should set this to true. Default behaviour autoguesses this.
#I'm not 100% sure these work correctly, please report bugs if you encounter them.
function textsubmodonp016(clip cs, string path, string "vfr", string "sm", bool "hack") {
c = cs.ditherpost(mode=8)
sm = defined(sm) ? sm : (c.width > 1024 || c.height > 600) ? "Rec709" : "Rec601"
hack = defined(hack) ? hack : sm == "Rec709" ? true : sm == "PC.709" ? true : false
bc = blankclip(c,pixel_type="RGB32",color=$FF000000)#pure alpha
crgb = hack ? c.converttorgb32(matrix="Rec601") : c.converttorgb32(matrix=sm)
mergeargb(bc.showalpha(),crgb.showred(),crgb.showgreen(),crgb.showblue())
defined(vfr) ? textsubmod(path,vfr=vfr) : textsubmod(path)
mergeargb(showalpha().invert(),showred(),showgreen(),showblue())
savealpha = last
o = converttoyv24(matrix="Rec601").converttorgb32(matrix="Rec709")
return hack ? rgb32onp016(cs,mergeargb(savealpha.showalpha(),o.showred(),o.showgreen(),o.showblue()),sm=sm) : rgb32onp016(cs,last,sm=sm)
}
function textsubonp016(clip cs, string path, string "vfr", string "sm", bool "hack") {
c = cs.ditherpost(mode=8)
sm = defined(sm) ? sm : (c.width > 1024 || c.height > 600) ? "Rec709" : "Rec601"
hack = defined(hack) ? hack : sm == "Rec709" ? true : sm == "PC.709" ? true : false
bc = blankclip(c,pixel_type="RGB32",color=$FF000000)#pure alpha
crgb = hack ? c.converttorgb32(matrix="Rec601") : c.converttorgb32(matrix=sm)
mergeargb(bc.showalpha(),crgb.showred(),crgb.showgreen(),crgb.showblue())
defined(vfr) ? textsub(path,vfr=vfr) : textsub(path)
mergeargb(showalpha().invert(),showred(),showgreen(),showblue())
savealpha = last
o = converttoyv24(matrix="Rec601").converttorgb32(matrix="Rec709")
return hack ? rgb32onp016(cs,mergeargb(savealpha.showalpha(),o.showred(),o.showgreen(),o.showblue()),sm=sm) : rgb32onp016(cs,last,sm=sm)
}