View Full Version : drawbox function of ffmpeg in avisynth
Yanak
1st September 2017, 15:48
Hello,
Not sure if it's the right place to ask about this but will something similar to the drawbox (https://ffmpeg.org/ffmpeg-filters.html#drawbox) function of ffmpeg will be hard to implement in avisynth ? ( i know about overlay and Blackness/BlankClip in avisynth but i would like something a bit better that could combine and adjust with text sizes used in subtitle function)
In Ffmpeg this is handy, you can auto adjust the size of the box to a given text displayed using text_h & text_w functions of drawtext (https://ffmpeg.org/ffmpeg-filters.html#toc-drawtext-1),
similar thing is possible in php using imageftbbox or imagettfbbox that can calculate the space taken by some text then use imagefilledrectangle function to draw the box behind some text displayed using imagettftext function.
I'm not expert in all this, had to mess a few times with php draw functions and used those things, only used them a bit with ffmpeg but this is very helpful to kind of auto-draw boxes behind some text, can be full color or semi transparent boxes, so I'm wondering if something like this would be possible in avisynth somehow, will be a very neat thing imo, might be just me thinking this will be nice and you guys will throw stones at me for asking something stupid but i ask :p
So I'm wondering if something allowing us to define the text width and height could be done maybe, then creating a blankclip and overlay will be easier to auto adjust to some text or maybe have a combination of those 2 for a more automated process.
Thanks a lot and thanks again for this nice tool that is avisynth.
wonkey_monkey
1st September 2017, 18:51
Your question would be better off in Avisynth Usage (https://forum.doom9.org/forumdisplay.php?f=33) but the "textbook" answer that immediately springs to mind is to use crop(...) to split the clip into 9 boxes (well, 5, at a minimum, one either side and split the middle slice into 3), alter the middle one (darken it, blank it), then stack (stackhorizontal and stackvertical) them all back together again.
Yanak
1st September 2017, 20:32
Hi and thanks for the answer,
I can do some things already but it needs to be adjusted for each use so it's not exactly what i need, i want something way more precise than this and able to be semi automated.
To achieve it i need a function similar to what ffmpeg or php can do to get the height and width of the text input based on the font used and the font size set for the subtitle function to then be able to draw a semi transparent box just around the text very precisely.
Like i said i'm not sure how hard it will be to add such thing or even if it is possible in avisynth, I know it is possible on some other things like ffpmpeg or even in php wih functions i spoke about in my previous post.
For example some times ago i made me a small batch using ffmpeg to test a bunch of LUT .cube files applied on a single picture ( or entire videos extracting frames from it using ffprobe and making a grid with frames from the video ), the result will bring me the original picture with many different LUT's applied on it and the name of he LUT used will be drawed on the pictures + the semi transparent textbox that is dynamic and auto-adjust to the text input itself, the text font used and the font size used, like here :
https://s14.postimg.org/kchs8vrr5/82313220170901212208.gif
all this is automated, i don't need to adjust the black box behind, just a math formula on the batch based on the width and height the text will have using ffmpeg "text_h" & "text_w" functions.
To be able to reproduce something working similarly in avisynth when i use the subtitle function i need it to calculate the width and height the desired text input will take based on the text lenght, the font and fontsize used.
Like i said i'm not sure if this is possible to be implemented or if it is a headache to code something like this in avisynth or even if it is something relevant but having a function like this will be really nice.
Thanks.
wonkey_monkey
1st September 2017, 21:47
To be able to reproduce something working similarly in avisynth when i use the subtitle function i need it to calculate the width and height the desired text input will take based on the text lenght, the font and fontsize used.
You might be able to do something with rt_stats or similar (I'm not familiar enough with it to say if you can or can't) whereby you would feed it a subtitle clip and it could tell you the extent of the white pixels on it...
TheFluff
1st September 2017, 22:26
If you want a real subtitle renderer with full-featured typography, layouting and text extents calculation, how about you use one? There are several ways to do what you want with .ass-based subtitles and several ways to render them in Avisynth.
Yanak
1st September 2017, 22:58
@davidhorman:
thanks i will look into rt_stats documentation tomorrow and see if i can do something with this.
@TheFluff :
It ain't to use on full subtitles, not with subtitle files i mean, more like add a facility to add some background easily on some text i add on my videos using the subtitle functions of avisynth, mostly doing this using some functions and scripts i added inside staxrip with easy implementation there for those and semi-automation, like adding a caption on different parts of the video, selecting easily a portion of the video and extracting frame numbers then having an input textbox to add the text, select font size and position of the text, colors of text and halo etc etc, i have all pretty much automated and just need to input text, select font size, colors and positions mostly.
I'll just need a way to get the text width and height to add a nice background box almost automatically to all this but i understand this might be a specific request, i found some similar questions about this searching on the net before asking here if something could be done, was just wondering as this seems possible in some other domains and tools if this could be done here without much headache.
Thanks.
TheFluff
1st September 2017, 23:36
What you're describing is exactly what a subtitle renderer does. You can of course do things the hard way if you really insist, but I strongly believe that by far the easiest way to do what you're talking about is by generating an .ass file, programmatically if you want to. Take a look at Aegisub.
Yanak
2nd September 2017, 11:15
Thanks a lot for the replies and tips, i have looked into this but it ain't what i need sorry.
I asked thinking it might be possible to get such option implemented since it's something i saw and used in other domains and maybe something that is possible in the language used to code avisynth ( Im' not a coder so i don't know).
Just thinking avisynth could implement something like this natively and hopefully without much headache to code it, that could be handy and allow nice things to be done with/around subtitles and text implementation once avisynth is be able to return the height and width of the desired text input, adding a semi transparent box is only one of the possibilities, probably lot of other things/effects can be done around added text with such known parameters.
Well at least i tried, i guess I'll have to find another way using like suggested rt_stats maybe or something else or just pass and forget about this.
Thanks again for the replies and help.
poisondeathray
2nd September 2017, 17:33
Re-inventing the wheel. 1 spoke at a time :D:D . I'm with Fluffy - ASS subs have a textbox background style. You can make it semi transparent etc.. Lots of power in aegisub
But maybe one approach would be to use masktools to dynamically create a BG mask based on the parameters text/size/font/whatever
You can use mt_rectangle / mt_box to get rough box coordinates, but I don't know of an easy way to get a perfect box using masktools only , without some type of cropping , like autocrop. This means you lose the internal subtitle(x,y) position coordinates, but instead have to use mt_merge or overlay 's x,y positioning coordinates
This is very rough, but I think something like this might be close to what you want, or at least get you started . To debug it for now, you can enter the parameters up top, like font, color etc... . You can probably wrap it into a some function later once it's debugged more thoroughly. You might need to adjust the masktools parameters if you have extreme fonts or sizes
#Parameters
#############################
txt="This is my text, DUDE"
sz=40
ft="arial"
x_pos=100
y_pos=100
bg_color=color_blue
bg_opacity=0.5
txt_color=color_yellow
hal_color=color_black
#############################
orig=colorbars(pixel_type="YV12")
bl=blankclip(orig, pixel_type="YV12")
txtmsk=bl.subtitle(txt, font=ft, text_color=color_white, halo_color=color_white,size=sz)
txtmsk
mt_luts( last,last, mode = "max", pixels = mt_rectangle(6,6,true), expr = "y")
msk=last
msk
autocrop(mode=0, threshold=20)
mt_lut("255") #pure white mask
crpmsk=last
crpmsk
mt_lut("0") #pure black mask
bl_crpmsk=last
txt_alpha_msk=bl_crpmsk.subtitle(txt, font=ft, text_color=color_white, halo_color=color_white,size=sz)
txtlayer=bl_crpmsk.subtitle(txt, font=ft, text_color=txt_color, halo_color=hal_color,size=sz)
bg_for_txt=blankclip(bl_crpmsk, color=bg_color)
overlay(orig, bg_for_txt, x=x_pos,y=y_pos, opacity=bg_opacity)
overlay(last, txtlayer, x=x_pos,y=y_pos, mask=txt_alpha_msk)
https://s26.postimg.org/t8vvrqyi1/image.png (https://postimages.org/)
Yanak
2nd September 2017, 20:03
Thanks you very much for this,
i cannot test it tonight but will test all this deeply tomorrow and see how it goes and probably mess a bit with it if needed in the next days to adjust a few things but your approach looks nice presented like this.
Thanks a lot for this precious help.
Yanak
4th September 2017, 09:57
Had time to test and mess a bit with the script proposed and it works nicely, nice job on that, for this purpose while not 100% perfect or precise as i'd wanted it will do the job nicely, will have to spend time learning a bit more about masktools options to maybe improve it a bit and work on making all this more automated but it's something really nice already, again thanks a lot for the help.
Still wondering about something, the subtitles options have the "align" parameter, for example using align=9 or 3 will put the subs on the top right or bottom right of the screen, using align=5 will perfectly center the subtitles on the middle of the video for the width.
Seeing this i am now wondering even more about this, seems like somehow there is already a built in function in avisynth to know what width the subtitle will take to be able to use the align functions i guess, unless my reasoning is messed up and wrong there is already some sort of internal calculations done to define the length of the text and place it correctly using align functions to place the text on some parts of the screen no ?
Maybe something could be done using the same already built in function in avisynth that is used for align function but instead it will return the values calculated, again if my reasoning is correct here.
Thanks a lot.
poisondeathray
4th September 2017, 14:10
Still wondering about something, the subtitles options have the "align" parameter, for example using align=9 or 3 will put the subs on the top right or bottom right of the screen, using align=5 will perfectly center the subtitles on the middle of the video for the width.
Seeing this i am now wondering even more about this, seems like somehow there is already a built in function in avisynth to know what width the subtitle will take to be able to use the align functions i guess, unless my reasoning is messed up and wrong there is already some sort of internal calculations done to define the length of the text and place it correctly using align functions to place the text on some parts of the screen no ?
Maybe something could be done using the same already built in function in avisynth that is used for align function but instead it will return the values calculated, again if my reasoning is correct here.
I doubt using subtitle() 's align would be accurate enough for what you want. You have a grid of 3x3. The BG box will be pretty ugly with overhang on one or more sides depending on your test
Someone should be able to look at the -vf drawbox/drawtext code and translate it directly . Or why not use ffmpeg directly ?
raffriff42
5th September 2017, 04:49
Subtitle calls the Windows API function DrawText(... DT_CALCRECT) (http://avisynth2.cvs.sourceforge.net/viewvc/avisynth2/avisynth/src/filters/text-overlay.cpp?view=markup#l1830) to determine the bounding rectangle of the text as rendered.
Someone could make the results available to the user somehow, if they were sufficiently motivated.
(EDIT but poisondeathray's solution works great, so I don't see the need)
Yanak
5th September 2017, 09:01
@poisondeathray : in most cases i could test it is quite accurate to define the length of the text and place it correctly on screen and it adjusts to the length of the text input.
I can use ffmpeg for some things indeed, for some others i would like to get this directly in avisynth with a easy way to do this, all that is needed is being able to get text height and size, could then also bypass the "align" function and get more control on all this, once you know the width and height of the desired text input it takes just a few simple math formulas in the script that will bring a lot of liberty and new possibilities with all this.
@raffriff42, i was suspecting it was using something like this to define the size of the text and be able to place it correctly, i don't understand the code in the link , sadly this isn't my thing, but as far as i know there is usually 2 ways to define such used space, one takes in account the inter lines spacing and gives less accurate results, especially for the height calculation, other is based purely on the text input and gives really precise results for width and height, not taking in account the interline spaces.
In avisynth i suspect it uses the first one as when for example you use "Align=5" the text is ( as far as i could test) perfectly centered for the width, same free space remains on right and left sides, same exact space in pixels, but for the height it is not perfectly centered, probably due to the interline space parameter of the font that is included in the calculation here, not sure if what i tried to explain is easy to understand or not so a picture is better than words i guess :
https://s14.postimg.org/78c7w5pep/420452colorbars0.jpg
The align parameter depending the parameters, especially the font size can bring very nice results and some less nicer due to this method of calculation including the interline ( it's a guess only, don't take this for set in stone, just empiric reasoning) , with quite large font sizes you will have spaces and margins quite big from the bottom of the screen for example, again an example , with font size =30 :
https://s14.postimg.org/t7imjddyp/148354colorbars3.jpg
with font size= 100 :
https://s14.postimg.org/q0o2zr18h/247114colorbars2.jpg
(Edit: here there is no letter like "j,g" but even including this margin for such letters it won't be centered, maybe if it's not the interline space it could be the space for under lined text, i'm not 100% sure and did not tested with under lined text, will have too try if it is possible to be done in a subtitle)
Align parameter uses pre-defined margins, from the documentation :
x = 8 if align=1,4,7 or none; -1 if align=2,5,8; or width-8 if align=3,6,9
y = size if align=4,5,6 or none; 0 if align=7,8,9; or height-1 if align=1,2,3
those "margins" can be bypassed and set in the script too in combination with align parameter, for example : "x=video_width -3, y=video_Height, align= 3"," and will need a few adjustments depending the font sizes used to get the best looking results but it's already looking quite good with align parameter doing a nice job calculating the text space needed.
Like you said it could be interesting to get an option for those values able to be returned to the user, since they are calculated already in this process a function to get those values will not hurt much i think and only offer more possibilities to the end user, after all avisynth+ is "+" so getting more options and possibilities on the top of the existing ones can only be a good thing for the end user, more choices, more control and possibilities ^^
Thanks a lot.
TheFluff
5th September 2017, 12:18
Accurately determining the bounding box for a given string when rendered with a given typographic configuration essentially requires rendering that string with all the typographic bells and whistles enabled (kerning, ligatures, font substitution, hinting, etc etc etc - typography is really complex). That's why drawing background boxes tends to be a part of the subtitle rendering itself.
What you want is essentially programmable text layouting, which is prrretty far out of the scope of Avisynth builtins. As previously pointed out, good tools for this purpose do exist - they just aren't intended for use in Avisynth script. See for example Aegisub's scripting module and the text_extents (http://docs.aegisub.org/3.2/Automation/Lua/Miscellaneous_APIs/#aegisubtextextents) function.
I feel like I keep getting back to this piece of advice over and over on d9, but I'll repeat it again: even though you can do a lot with just Avisynth script, it may, at times, not be the right tool for the job. It is a domain-specific language designed for manipulating filter chains, and it's actually pretty good at that, but it's pretty awkward for pretty much everything else.
StainlessS
5th September 2017, 16:58
The Fluff is quite correct, but if you do intend to mess with avs,then a few links to subs threads.
http://forum.doom9.org/showthread.php?p=1658543
http://forum.doom9.org/showthread.php?t=170953
http://forum.doom9.org/showthread.php?p=1801206
https://forum.doom9.org/showthread.php?t=167877
EDIT: This vertically centers (instead of top of text vertically centered)
#Avisource("D:\avs\test.avi")
Colorbars.killaudio
Function SubV(clip c, string text, float "x", float "y", int "first_frame", int "last_frame", string "font", float "size", \
int "text_color", int "halo_color", int "align", int "spc", int "lsp", float "font_width", float "font_angle", bool "interlaced", \
bool "vcenter") { # http://forum.doom9.org/showthread.php?p=1628899#post1628899
c
GScript("""
size=Default(size,18)
vcenter=Default(vcenter,false)
if(Defined(align) && Defined(lsp)) {
if((align>=4 && align<=6) && vcenter) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=(Height/2) - ((Lines-1) * (size + lsp/8.0) / 2.0)
} else if(align>=1 && align<=3) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=Height - ((Lines-1) * (size + lsp/8.0))
}
}
""")
Subtitle(text,x,y,first_frame,last_frame,font,size,text_color,halo_color,align,spc,lsp,font_width,font_angle,interlaced)
}
VC=True
#VC=False
S="The\nQuick\nBrown\nfox\njumped\nover\nthe\nlazy\ndog.\nThe\nQuick\nBrown\nfox\njumped\nover\nthe\nlazy\ndog.\n"
SubV(S,lsp=0,align=4,vcenter=VC)
SubV(S,lsp=0,align=5,vcenter=VC)
SubV(S,lsp=0,align=6,vcenter=VC)
VC=True
https://s20.postimg.cc/exq34tfct/Test.jpg (https://postimages.cc/)
VC=False
https://s20.postimg.cc/c4wvksf0d/subs_false.jpg (https://postimages.cc/)
Function SubtitleCharSet() { # http://forum.doom9.org/showthread.php?p=1693672#post1693672
GSCript("""
S=""
for(y=0,15) {
s=s+"$"+RT_Hex(y*16,2)+ " "
for(x=0,15) {
n=y*16+x
c=(n<32) ? "." : Chr(n)
s=s+c
}
s=s+"\n"
}
""")
S
}
colorbars(width=360,height=512).Trim(0,-1)
s=RT_StrReplace(SubtitleCharSet,Chr(10),"\n")
Subtitle(s,font="Courier New",size=32,lsp=0)
return Last
Fixed Font Courier New Character Set (fixed size both horizontal and vertical)
https://s20.postimg.cc/pacdqw8vx/Fixed_Font_Courier_New.jpg (https://postimages.cc/)
EDIT: Or a bit of both
Function SubV(clip c, string text, float "x", float "y", int "first_frame", int "last_frame", string "font", float "size", \
int "text_color", int "halo_color", int "align", int "spc", int "lsp", float "font_width", float "font_angle", bool "interlaced", \
bool "vcenter") { # http://forum.doom9.org/showthread.php?p=1628899#post1628899
c
GScript("""
size=Default(size,18)
vcenter=Default(vcenter,false)
if(Defined(align) && Defined(lsp)) {
if((align>=4 && align<=6) && vcenter) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=(Height/2) - ((Lines-1) * (size + lsp/8.0) / 2.0)
} else if(align>=1 && align<=3) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=Height - ((Lines-1) * (size + lsp/8.0))
}
}
""")
Subtitle(text,x,y,first_frame,last_frame,font,size,text_color,halo_color,align,spc,lsp,font_width,font_angle,interlaced)
}
Function SubtitleCharSet() { # http://forum.doom9.org/showthread.php?p=1693672#post1693672
GSCript("""
S=""
for(y=0,15) {
s=s+"$"+RT_Hex(y*16,2)+ " "
for(x=0,15) {
n=y*16+x
c=(n<32) ? "." : Chr(n)
s=s+c
}
s=s+"\n"
}
""")
S
}
colorbars.Killaudio
S=SubtitleCharSet
SubV(s,font="Courier New",size=24,align=5,lsp=0,vcenter=True)
return Last
https://s20.postimg.cc/lf8zobpq5/Centered_Character_Set.jpg (https://postimages.cc/)
raffriff42
5th September 2017, 19:44
when for example you use "Align=5" the text is ( as far as i could test) perfectly centered for the width, same free space remains on right and left sides, same exact space in pixels, but for the height it is not perfectly centered, probably due to the interline space parameter of the font that is included in the calculation here
I believe that's due to the font descender (https://en.wikipedia.org/wiki/Descender) ('y', 'p', 'q' etc) dimension -- there are no descenders in your example, but room is allowed for them nonetheless. Smarter type tools probably don't have this issue. Subtitle is for "quick and dirty" work. It was never meant for professional typography.
StainlessS
5th September 2017, 20:21
I think that top align, aligns top of enclosing box, (incl spacing)
Mid align aligns to base line (bottom of caps letter),
bottom align with bottom of enclosing box. (incl spacing)
Blankclip(width=128,height=128)
s ="yTEXTy"
s1="yTEXT"
s2="TEXTy"
Subtitle(s,x=0,y=0) # align top
X=Width/2 ZX=25
Y=Height/2
Subtitle(s1,align=5,x=x-ZX) # mid align
Subtitle(s2,x=X+0,Y=Y-14.5) # maybe @ default sz 14 to baseline and 0.5 relative center ie height/2 - 0.5(even number of rows)
Subtitle(s,align=2) # bot align
BicubicResize(width*4,height*4)
M=Last.blankclip(width=32,height=4,color=$FFFFFF)
Overlay(Last,m,x=0,y=height/2-2)
Overlay(Last,m,x=width-32,y=height/2-2)
return last
Leastwise thats how it seems to me
https://s20.postimg.cc/6xbsgbyf1/Align_Cent_Y.jpg (https://postimages.cc/)
Yanak
5th September 2017, 22:46
Hi,
@raffriff42,
yeah i spoke about those in the edit i added under one of the pictures, while i did not used those characters in the example it still won't be perfectly centered with them in the tests i made, might be in case of underlining text is used or something else like the possibility to add accents on capital letters for example like "É" or might be something else, i don't know.
Googling one of the parameters in the link you posted i found this https://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx , plenty of parameters and some like seems to indicate it is possible to fine tune this and get more accurate results for the box, maybe "DT_BOTTOM" will bring better results, well i'm not coder but seems like there is a few options to mess with this.
@TheFluff,
i perfectly understand there is tools done specifically for this, and while it's not the main purpose of avisynth to do such things it's one of his features, a handy one, some things could be improved and offer new possibilities in this domain, like avs+ not long ago allowed the use of non installed fonts.
Here avisynth already have the code used in it to calculate this for the align functions, it already calculates the text sizes, adding a little extra option able to return those already calculated results to the end user would be nice and offer more possibilities, that's all i am saying.
@StainlessS : i will try all those scripts tomorrow and also try to understand them, you guys amaze me with the creativity you have and how all this seems simple for you, myself i struggle a bit more with all this and work more by trial and error. Will spend time tomorrow processing some tests with all this, thanks a lot for the help and scripts, really appreciate all the effort you guys done.
Again thanks to all for all this, i guess now i can only hope one of those days someone will find the idea of making an option returning the already calculated text size using the already present code for this in avisynth might be something that could offer some nice options and worth the effort.
Thank you all.
raffriff42
7th September 2017, 03:31
Here's my take, building on poisondeathray's idea.
https://www.dropbox.com/s/cpd0getb282uo9c/text-bounds1s.jpg?raw=1 (https://www.dropbox.com/s/nxg1pvkngs9fymv/text-bounds1.png?raw=1) https://www.dropbox.com/s/ni9dn15ohdwuufv/text-bounds4s.jpg?raw=1 (https://www.dropbox.com/s/dnd8nkrt32a1140/text-bounds4.png?raw=1) https://www.dropbox.com/s/n5167sinuplwfx1/text-bounds3s.jpg?raw=1 (https://www.dropbox.com/s/m2h6uhtis9q4z2v/text-bounds3.png?raw=1)
LoadPlugin(pathBase + "AutoCrop\AutoCrop.dll")
fontface="Arial Bold Italic"
fontsize=32
textcolor=color_yellow
halocolor=color_blue
padding=4
x_adj=6 ## fudge factor
y_adj=6
msg="""
In the beginning the Universe was created.
This has made a lot of people very angry
and been widely regarded as a bad move.
"""
## next 2 lines needed only if using multiline style above
msg=MidStr(msg, 3)
msg=ReplaceStr(msg, Chr(10), "\n")
orig=Colorbars(pixel_type="YV12")
## /end user params
Blankclip(orig)
Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=$ffffff, halo_color=$ffffff,
\ lsp=fontsize)
## (faster than mt_rectangle)
mt_expand.mt_expand.mt_expand
mt_expand.mt_expand.mt_expand
GrayScale
AutoCrop(mode=0, threshold=20)
## optional padding
AddBorders(padding, padding, padding, padding)
box=Last
#return box
bl2=Blankclip(box)
txt=bl2.Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=textcolor, halo_color=halocolor,
\ x=x_adj, y=y_adj, lsp=fontsize)
#return txt
msk=bl2.Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=$ffffff, halo_color=$ffffff,
\ x=x_adj, y=y_adj, lsp=fontsize)
## expand mask to 0-255 range (there are prob. better ways to do this)
msk=msk.Levels(18, 1, 232, 0, 255, coring=false)
#return msk
## output example 1: center on screen
#orig.Overlay(txt, mask=msk,
#\ x=orig.Width/2-txt.Width/2,
#\ y=orig.Height/2-txt.Height/2)
## output example 2: bottom-right
orig.Overlay(txt, mask=msk,
\ x=orig.Width-txt.Width,
\ y=orig.Height-txt.Height)
return Last
poisondeathray
7th September 2017, 04:28
Stainless - is that the full/verbose character map in post #16?
I'm just playing around entering values and I get some character's not on your screenshot
e.g
chr($12) gets me a double headed up/down arrow
chr($13) returns "!!"
What's the deal with subtitle() and alt keys ? You know the symbol stuff / wingdings etc... ? Some of them work like euro "€" , but many don't work and display incorrectly
Yanak said you can use other fonts with avisynth+ and that is news to me. Lo and behold, very cool stuff with utf8=true
I'm thinking that a full box character might used as the basis for a mask if the input text characters can be linked and replaced, especially if a unispace font is used
e.g. the text "hello" is replaced by "XXXXX" , but if you can use a chr(whatever) to get a " █ " , invert and use as a mask+/- expand . That way you keep the internal subtitle() arguments including align
txt="hello"
fill=FillStr(StrLen(txt), "X")
colorbars(pixel_type="yv12")
subtitle(fill)
Yanak
7th September 2017, 10:08
@raffriff42 : Will play a bit with this script and try to see what i can do with it, you guys go way too fast for me ^^
And yes you can now use any font you want, no need to install a font that you need to use only once or twice for a specific project : http://forum.doom9.net/showthread.php?p=1801206#post1801206 ,
nice option especially if you use some "exotic" fonts like those you can find in dafont.com for example, for some of the fonts i tried the scripts proposed seems to work, of course for some others it ends up messed up as they are really specific and exotic or more like symbols and drawings than fonts for some others but this ain't a problem, not the the thing i try to solve anyways.
Did not had much time to test with a lot of uft8 characters for now using the new "utf8=true" parameter too but this also brings new possibilities.
Thanks again for all guys.
StainlessS
7th September 2017, 14:49
PDR, I guess that the posted character set is just for the Courier New fixed font, with below mod (in RED) produces as in image
Colorbars.killaudio
Function SubV(clip c, string text, float "x", float "y", int "first_frame", int "last_frame", string "font", float "size", \
int "text_color", int "halo_color", int "align", int "spc", int "lsp", float "font_width", float "font_angle", bool "interlaced", \
bool "vcenter") { # http://forum.doom9.org/showthread.php?p=1628899#post1628899
c
GScript("""
size=Default(size,18)
vcenter=Default(vcenter,false)
if(Defined(align) && Defined(lsp)) {
if((align>=4 && align<=6) && vcenter) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=(Height/2) - ((Lines-1) * (size + lsp/8.0) / 2.0)
} else if(align>=1 && align<=3) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=Height - ((Lines-1) * (size + lsp/8.0))
}
}
""")
Subtitle(text,x,y,first_frame,last_frame,font,size,text_color,halo_color,align,spc,lsp,font_width,font_angle,interlaced)
}
Function SubtitleCharSet() { # http://forum.doom9.org/showthread.php?p=1693672#post1693672
GSCript("""
S=""
for(y=0,15) {
s=s+"$"+RT_Hex(y*16,2)+ " "
for(x=0,15) {
n=y*16+x
c=(n<1) ? "." : Chr(n) # Show chars 1 to 31
s=s+c
}
s=s+"\n"
}
""")
S
}
colorbars.Killaudio
S=SubtitleCharSet
SubV(s,font="Courier New",size=24,align=5,lsp=0,vcenter=True)
return Last
https://s20.postimg.cc/dsdnggzct/Character_Set2.jpg (https://postimages.cc/)
So I guess characters 1 -> 31 are valid for some character sets.
EDIT: With non-fixed font character set would be higgledy piggledy.
EDIT: Using default font, chars 1->31 also not defined
https://s20.postimg.cc/7suy9xkvx/Character_Set3.jpg (https://postimages.cc/)
EDIT: I'm on avs standard v2.6 and no utf8.
EDIT: Above vertical centering is a bit off, due to sub() seeing FONT Chr(10) as new line and screws up centering.
poisondeathray
7th September 2017, 15:09
Maybe windows version difference ? Win8.1 x64 I get those with arial or courier new
(This was on vanilla avisynth x86, not avisynth+ x64 or utf8 testing)
https://s26.postimg.org/xkrae8ujt/huh.png (https://postimages.org/)
colorbars()
subtitle(chr($12),size=24)
subtitle(chr($13),size=24,y=24)
StainlessS
7th September 2017, 15:30
Link to UK car number plate Mandatory “Charles Wright” font, I've posted link before in thread about a user victim of burglary, but the
thread was deleted (probably to not interfere with the trial process):- http://www.dafont.com/uk-number-plate.font
NOTE, I think I recall some kind of condition to having above linked font on your machine, you have also to have some kind
of copyright thing, else possession considered to be illegal (in the UK).
EDIT: Some more:- https://www.nationalnumbers.co.uk/blog/2016/01/complete-guide-number-plate-fonts.html
And more: https://www.whatdotheyknow.com/request/registration_plate_font
And yet more:- http://www.fontspace.com/category/license%20plate
EDIT: I'm on XP32
Despite Mandatory UK number plate being described as "Mono Spaced except for i/1", it is not.
(EDIT: Perhaps Mono Spaced for CAPS and DIGITS only)
https://s20.postimg.cc/dib6u8r25/Charset_Mandatory.jpg (https://postimages.cc/)
EDIT: Here an odd font, "BookShelf Symbol 7", two swastikas and a star of David in same font:-
EDIT: Think this font has been deleted from Windows [maybe post XP].
https://s20.postimg.cc/9zz6xuq65/Charset_Book_Shelf_Symbol7.jpg (https://postimages.cc/)
StainlessS
7th September 2017, 18:48
You can use mt_rectangle / mt_box to get rough box coordinates, but I don't know of an easy way to get a perfect box using masktools only , without some type of cropping , like autocrop.
PDR, does this assist at all ?
Function BoxMask(clip c, Int "X", Int "Y", Int "W", Int "H",Int "BW",Int "BH",Bool "Y8") {
/*
Return a single frame mask for a box # http://forum.doom9.org/showthread.php?p=1817736#post1817736
c, clip, template for frame size.
X,Y,W,H Box dimensions all default 0, as for crop eg 0,0,0,0 = full frame.
BW, Default=0=Solid box. Frame width for uprights.
BH, Default=BW, Frame height for horizontals.
Y8, Default False=YV12.
Req MaskTools v2.0
*/
c myName="BoxMask: " x=Default(x,0) y=Default(y,0) W=Default(W,0) H=Default(H,0) BW=Default(BW,0) BH=Default(BH,BW) Y8=Default(Y8,False)
W=(W<=0) ? Width-X+W : W H=(H<=0) ? Height-Y+H : H
Assert(0 <= X < Width, myName+String(X,"0 <= X(%.0f) < ")+String(Width, "Width( %.0f)"))
Assert(0 <= Y < Height,myName+String(Y,"0 <= Y(%.0f) < ")+String(Height,"Height(%.0f)"))
Assert(0 < W <= Width, myName+String(W,"0 < W(%.0f) <= ")+String(Width, "Width( %.0f)"))
Assert(0 < H <= Height,myName+String(H,"0 < H(%.0f) <= ")+String(Height,"Height(%.0f)"))
Assert(0 <= BW <= W/2,myName+String(BW,"0 <= BW(%.0f) <= ")+String(W/2,"W/2(%.0f)"))
Assert(BW==0 || (0 < BH <= H/2),myName+String(BH,"0 <= BH(%.0f) <= ")+String(H/2,"H/2(%.0f)"))
Rpn=(BW==0)
\ ? String(X,"x %.0f")+String(X+W," >= x %.0f")+String(Y," < & y %.0f")+String(Y+H," >= & y %.0f < & 255 0 ?")
\ : String(X,"x %.0f")+String(X+W," >= x %.0f")+String(Y," < & y %.0f")+String(Y+H," >= & y %.0f < &") +
\ String(X+BW," x %.0f")+String(X+W-BW," < x %.0f")+String(Y+BH," >= | y %.0f")+String(Y+H-BH," < | y %.0f >= | & 255 0 ?")
return Last.Blankclip(Length=1,pixel_type=(Y8)?"Y8":"YV12").mt_lutspa(relative=false,Yexpr=Rpn, chroma = "-128" )
}
ColorBars.Killaudio
Mask=BoxMask(x=4,y=4,w=-4,h=-4,Bw=10)
Overlay(Last.BlankClip(Color=$FF0000),Mask=Mask)
return last
Raw mask
https://s26.postimg.cc/t4b75h5s9/Mask.jpg (https://postimages.cc/)
with Overlay
https://s20.postimg.cc/lxidss0e5/Box_Mask.jpg (https://postimages.cc/)
EDIT: Yanak, see here:- http://forum.doom9.org/showthread.php?p=1813402#post1813402
EDIT: PDR, what you get for Chr(10) on your ver$ windows ?
StainlessS
8th September 2017, 06:37
Fixed align=1, or 2 or 3 bottom alignment for multi-line strings.
Function SubV(clip c, string text, float "x", float "y", int "first_frame", int "last_frame", string "font", float "size", \
int "text_color", int "halo_color", int "align", int "spc", int "lsp", float "font_width", float "font_angle", bool "interlaced", \
bool "vcenter") { # http://forum.doom9.org/showthread.php?p=1628899#post1628899
c
GScript("""
size=Default(size,18)
vcenter=Default(vcenter,false)
if(Defined(align) && Defined(lsp)) {
if((align>=4 && align<=6) && vcenter) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=(Height/2) - ((Lines-1) * (size + lsp/8.0) / 2.0)
} else if(align>=1 && align<=3) {
s=RT_StrReplace(text,"\n",Chr(10),Sig=false)
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
y=Height - ((Lines-1) * (size + lsp/8.0))
}
}
""")
Subtitle(text,x,y,first_frame,last_frame,font,size,text_color,halo_color,align,spc,lsp,font_width,font_angle,interlaced)
}
EDIT: Renamed SubV()
StainlessS
8th September 2017, 07:12
Fountain, subtitle renderer.
Function Fountain(clip c,String CSV,String "Separator",String "StrDelimiter",Int "MaxTextLen") {
/*
Fountain(), http://forum.doom9.org/showthread.php?p=1818026#post1818026
Function taking a CSV file (Comma Separated Values), of Subtitle Arguements, prints Subtitles on frame.
Requirements:-
RT_Stats v2.0, CallCmd (Used if available, if not then cannot delete DBase file after clip closure), (c) StainlessS.
Masktools v2.0, (c) Pinterf+Others.
GScript, Grunt, (c) Gavino.
CSV, FileName of a text CSV (Comma Separated Value) file.
Value_number SubTitle_Arg, Comments
0) First_frame Start frame for a subtitle
1) Last_frame End frame for a subtitle (0=Last frame, -10 = 10 frames. All sequences/ranges be ordered)
2) X X position, -1 acts as UnDefined
3) Y Y position, -1 acts as UnDefined
4) Text Subtitle Text. Must be no longer than MaxTextLen
5) Font Font name. "" acts as Default "Ariel".
6) Size Font Size. -1.0 acts as default 18.0.
7) Text_color Text color. -1 acts as default Yellow $FFFF00
8) Halo_color Halo color. -1 acts as default Black $000000
9) Align Text Alignment. -1 acts as default 7.
10) Spc Font Spacing, normal=0.
11) Lsp Mutliline. -1 acts as Default Undefined. 0.0=no extra line spacing, switch on Multi-line.
12) Font_Width Font width. use 0.0 for system default.
13) Font_Angle Font Angle. Use 0.0 for system default.
14) Interlaced Bool, Clip is interlaced.
15) VCenter Vertical Center text, when lsp Defind and align=4, 5, or 6.
16) BackGround_W 0=OFF. 0 < BackGround_W, Left & Right outside background box.
17) BackGround_H 0=OFF. 0 < BackGround_H, Top & Bot outside background box.
18) BackGround_Color Background box color.
19) BackGround_Opacity Background box opacity.
Separator Default "," ie comma separator (first character only, Chr()'s 0, 13, 10, and 34 [Double Quote] illegal).
Default Separator "," (Comma) is optional and so long as CSV values are SPACE/TAB separated will not produce an error
if separator is missing.
StrDelimiter Default = "\"" ie single character string Double Quote.
StrDelimiter (String Delimiter) can be multiple characters (empty string "" illegal, also cannot contain the Separator
character nor SPACE or TAB), Default is a Double Quote single character string.
CSV string values CANNOT contain StrDelimiter string, ie for default StrDelimiter, strings cannot contain a double
quote character string. So long as the StrDelimiter does not appear within any string, nearly any StrDelimiter can be
used, eg "@@@" is a 3 character StrDelimiter that you could use in place of double quote string delimiters, where the
string values could then contain a double quote character, in such a case you should enclosed CSV strings as in
@@@Some text that contains a " double quote.@@@.
NOTE, StrDelimiter IS case sensitive, so if using alphabetic characters they have to match exactly.
MaxTextLen Default 256. Max Length of Subtitle Text.
*/
myName="Fountain: "
Assert(RT_FunctionExist("GScriptClip"),RT_String("%sEssential GRunT plugin installed, http://forum.doom9.org/showthread.php?t=139337",myName))
Assert(RT_FunctionExist("GScript"),RT_String("%sEssential GScript plugin installed, http://forum.doom9.org/showthread.php?t=147846",myName))
Assert(RT_FunctionExist("RT_DBaseReadCSV"),
\ RT_String("%sEssential RT_Stats v2.0 plugin installed, http://forum.doom9.org/showthread.php?p=1808953#post1808953",myName))
Assert(CSV!="",RT_string("%sNeed CSV Filename",myName))
MaxTextLen=Default(MaxTextLen,256)
IsCallCmd = RT_FunctionExist("CallCmd")
FuncS="""
Function Fn@@@(clip c,string DB) {
c
n = current_frame
if(PREV_FRAME@@@ + 1 != n || (CURRENT_SEQ@@@<0 || n > LAST_FRAME@@@)) {
SEQ = RT_DBaseFindSeq(DB,0,1,n) Global CURRENT_SEQ@@@=SEQ
if(SEQ>=0) { # New Subtitle range found
Global FIRST_FRAME@@@ = RT_DBaseGetField(DB,SEQ,0) Global LAST_FRAME@@@ = RT_DBaseGetField(DB,SEQ,1)
Global X@@@ = RT_DBaseGetField(DB,SEQ,2) Global Y@@@ = RT_DBaseGetField(DB,SEQ,3)
Global TEXT@@@ = RT_DBaseGetField(DB,SEQ,4) Global FONT@@@ = RT_DBaseGetField(DB,SEQ,5)
Global SIZE@@@ = RT_DBaseGetField(DB,SEQ,6) Global TCOLOR@@@ = RT_DBaseGetField(DB,SEQ,7)
Global HCOLOR@@@ = RT_DBaseGetField(DB,SEQ,8) Global ALIGN@@@ = RT_DBaseGetField(DB,SEQ,9)
Global SPC@@@ = RT_DBaseGetField(DB,SEQ,10) Global LSP@@@ = RT_DBaseGetField(DB,SEQ,11)
Global FONT_WIDTH@@@ = RT_DBaseGetField(DB,SEQ,12) Global FONT_ANGLE@@@ = RT_DBaseGetField(DB,SEQ,13)
Global INTERLACED@@@ = RT_DBaseGetField(DB,SEQ,14) Global VCENTER@@@ = RT_DBaseGetField(DB,SEQ,15)
Global OUTER@@@_W = RT_DBaseGetField(DB,SEQ,16) Global OUTER@@@_H = RT_DBaseGetField(DB,SEQ,17)
Global OCOLOR@@@ = RT_DBaseGetField(DB,SEQ,18) Global BKOPACITY@@@ = RT_DBaseGetField(DB,SEQ,19)
# Defaults
Global X@@@ = (X@@@==-1) ? RT_Undefined : X@@@ Global Y@@@ = (Y@@@==-1) ? RT_Undefined : Y@@@
Global FONT@@@= (FONT@@@=="") ? "Ariel" : FONT@@@ Global SIZE@@@= (SIZE@@@==-1.0) ? 18.0 : SIZE@@@
Global TCOLOR@@@=(TCOLOR@@@==-1) ? $00FFFF00 : TCOLOR@@@ Global HCOLOR@@@=(HCOLOR@@@==-1) ? $00000000 : HCOLOR@@@
Global ALIGN@@@= (ALIGN@@@==-1) ? 7 : ALIGN@@@ Global LSP@@@= (LSP@@@==-1) ? RT_Undefined : LSP@@@
if(LSP@@@.Defined) { # Multi-line correction of vertical center and bottom alignment.
if(VCENTER@@@ && ALIGN@@@>=4 && ALIGN@@@<=6) {
s=RT_StrReplace(TEXT@@@,"\n",Chr(10))
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
Global Y@@@=(c.Height/2) - ((Lines-1) * (SIZE@@@ + LSP@@@/8.0) / 2.0)
} else if(ALIGN@@@>=1 && ALIGN@@@<=3) {
s=RT_StrReplace(TEXT@@@,"\n",Chr(10))
Lines = RT_TxtQueryLines(s) # Line count with/without final newline
Global Y@@@=c.Height - ((Lines-1) * (SIZE@@@ + LSP@@@/8.0))
}
}
if(OUTER@@@_W>0||OUTER@@@_H>0) { # Calc box coords
CTemp=c.BlankClip(Length=1,pixel_type="Y8").mt_lut("0") # Pure black (Luma=0)
CTemp=CTemp.Subtitle(TEXT@@@,x=X@@@,y=Y@@@,font=FONT@@@,size=SIZE@@@,
\ text_color=$FFFFFF,halo_color=$FFFFFF,align=ALIGN@@@,
\ spc=SPC@@@,lsp=LSP@@@,font_width=FONT_WIDTH@@@,font_angle=FONT_ANGLE@@@,Interlaced=INTERLACED@@@)
Global Bingo@@@=CTemp.RT_YInRangeLocate(n=0,Baffle=1,Lo=16,Hi=255,Prefix="YIRL@@@_") # Locate text Incl halo
if(Bingo@@@) { # successful location
x1=Max(YIRL@@@_X-OUTER@@@_W,0) x2=Min(YIRL@@@_X+YIRL@@@_W+OUTER@@@_W,CTemp.Width)
y1=Max(YIRL@@@_Y-OUTER@@@_H,0) y2=Min(YIRL@@@_Y+YIRL@@@_H+OUTER@@@_H,CTemp.Height)
RPN=RT_String("x %d >= x %d < & y %d >= & y %d < & 255 0 ?",x1,x2,y1,y2)
Global Mask@@@=CTemp.BlankClip.mt_lutspa(relative=false,Yexpr=Rpn, chroma = "-128" ) # Background mask
}
}
}
}
if(CURRENT_SEQ@@@>=0) { # We have a current subtitle range
if((OUTER@@@_W>0||OUTER@@@_H>0) && Bingo@@@) { # Background box required
Last.Overlay(Last.BlankClip(Color=OCOLOR@@@),Mask=Mask@@@,Opacity=BKOPACITY@@@)
}
Subtitle(TEXT@@@,x=X@@@,y=Y@@@,font=FONT@@@,size=SIZE@@@,
\ text_color=TCOLOR@@@,halo_color=HCOLOR@@@,align=ALIGN@@@,
\ spc=SPC@@@,lsp=LSP@@@,font_width=FONT_WIDTH@@@,font_angle=FONT_ANGLE@@@,Interlaced=INTERLACED@@@)
}
Global PREV_FRAME@@@ = n # Remember previous frame visited for next iteration
Return Last
}
#######################################
# Unique Global Variables Initialization
#######################################
Global PREV_FRAME@@@ = -666 # Init
Global CURRENT_SEQ@@@ = -1 # Init
#
CSV=RT_GetFullPathName(CSV)
Assert(Exist(CSV),RT_String("%s CSV file '%s' does not exist",myName,CSV))
DB=RT_GetFullPathName(RT_LocalTimeString(file=True)+".DB")
RT_DBaseAlloc(DB,0,RT_String("iiffs%ds128fiiiiiffbbiiif",MaxTextLen))
RT_DBaseReadCSV(DB,CSV)
Records=RT_DBaseRecords(DB)
# Check ranges legality
Prev_Last_Frame=-1
for(i=0,Records-1) {
first_frame=RT_DBaseGetField(DB,i,0)
Assert(Prev_Last_Frame<first_frame,RT_String("%sSubtitles Overlap : Prev_last_frame=%d First_frame=%d",myName,Prev_last_frame,First_frame))
Assert(first_frame<=c.FrameCount-1,RT_String("%sfirst_frame out of clip(%d)",myName,first_frame))
last_frame=RT_DBaseGetField(DB,i,1)
if(last_frame<=0) {
last_frame=(last_frame==0) ? c.FrameCount-1 : first_frame-Last_frame-1
RT_DBaseSetField(DB,i,1,last_frame)
}
Assert(first_frame <= last_Frame <= c.FrameCount-1,RT_String("%sIllegal last_frame(%d)",myName,last_Frame))
Prev_Last_Frame=last_Frame
}
#######################################
# Unique Runtime Call, GScriptClip must be a one-liner:
#######################################
ARGS = "DB"
c.GScriptClip("Fn@@@(last, "+ARGS+")", local=true, args=ARGS)
(IsCallCmd) ? CallCmd(Close="CMD /C del "+DB, Hide=true) : NOP # If CallCmd available, thebn auto Delete TEMP DB on clip closure.
"""
#######################################
# Unique Identifier Definition
#######################################
GIFunc ="FOUNTAIN" # Function Name, Supply unique name for your multi-instance function.
GIName =GIFunc+"_InstanceNumber" # Name of the Instance number Global
RT_IncrGlobal(GIName) # Increment Instance Global (init to 1 if not already exists)
GID = GIFunc + "_" + String(Eval(GIName))
InstS = RT_StrReplace(FuncS,"@@@","_"+GID)
# RT_WriteFile("DEBUG_"+GID+".TXT","%s",InstS) # UnComment to write each unique script function instance to log file
Return GScript(InstS)
}
SSS="""
100, 189,-1,-1,"Testing 123\nTimes New Roman", "Times New Roman", 30.0,$FF0000,$00FF00, 1,0,0,0.0,0.0,false,true, 4, 4,$FF00FF,0.70
200, -90, -1,-1,"Testing 123\nAriel", "Ariel", 36.0,$00FF00,$FF0000, 2,0,0,0.0,0.0,false,true, 2, 2,$00FFFF,0.25
300, -90, -1,-1,"Testing 123\nCourier New", "Courier New", 38.0,$0000FF,$00FF00, 3,0,0,0.0,0.0,false,true, 8, 8,$8000FF,0.50
400, -90, -1,-1,"Testing 123\nBookman Old Style", "Bookman Old Style", 40.0,$FF0000,$00FF00, 4,0,0,0.0,0.0,false,true, 4, 4,$0080FF,0.25
500, -90, -1,-1,"Testing 123\nGigi", "Gigi", 64.0,$FFFFFF,$000000, 5,0,0,0.0,0.0,false,true, 0, 0,$FF00FF,0.10
600, -90, -1,-1,"Testing 123\nGoudy Stout", "Goudy Stout", 44.0,$FF0000,$00FF00, 6,0,0,0.0,0.0,false,true, 6, 6,$808080,1.00
700, -90, -1,-1,"Testing 123\nHaettenschweiler", "Haettenschweiler", 46.0,$208000,$000000, 7,0,0,0.0,0.0,false,true, 4, 4,$0080FF,0.50
800, -90, -1,-1,"Testing 123\nPalatino LinoType", "Palatino LinoType", 48.0,$FF0000,$F0E040, 8,0,0,0.0,0.0,false,true, 8, 8,$00FFFF,0.40
900, 989, -1,-1,"Testing 123\nCaladea", "Caladea", 50.0,$FFFF00,$FF0000, 9,0,0,0.0,0.0,false,true,12,12,$F000FF,0.25
1000,-90, -1,-1,"Testing 123\nBradley Hand ITC", "Bradley Hand ITC", 30.0,$FF0080,$F0FF0A, 1,0,0,0.0,0.0,false,true, 4, 4,$80F0FF,0.45
1100,-90, -1,-1,"Testing 123\nWingdings", "Wingdings", 36.0,$00FFFF,$000000, 2,0,0,0.0,0.0,false,true, 8, 8,$FFFF00,0.50
1200,-90, -1,-1,"Testing 123\nCalibri Bold", "Calibri Bold", 32.0,$004000,$FFFA00, 3,0,0,0.0,0.0,false,true,12,12,$FF00FF,0.30
1300,-90, -1,-1,"Testing 123\nCambria Bold", "Cambria Bold", 48.0,$000FFF,$A0FF40, 4,0,0,0.0,0.0,false,true, 4, 4,$0000FF,0.90
1400,-90, -1,-1,"Testing 123\nCentury Gothic", "Century Gothic", 42.0,$F08040,$0AFF80, 5,0,0,0.0,0.0,false,true, 8, 8,$80A0FF,0.70
1500,-90, -1,-1,"Testing 123\nConstantia Bold", "Constantia Bold", 36.0,$800000,$0FFF0F, 6,0,0,0.0,0.0,false,true,12,12,$4090FF,0.30
1600,-90, -1,-1,"Testing 123\nCopperplate Gothic Bold", "Copperplate Gothic Bold", 44.0,$FFFFFF,$000000, 7,0,0,0.0,0.0,false,true, 4, 4,$FF80F0,0.60
1700,-90, -1,-1,"Testing 123\nCurlz MT", "Curlz MT", 38.0,$FF0000,$000000, 8,0,0,0.0,0.0,false,true, 8, 8,$00FFF0,0.40
1800,-90, -1,-1,"Testing 123\nElephant", "Elephant", 44.0,$FF0000,$00FFF0, 9,0,0,0.0,0.0,false,true,12,12,$0FF800,0.25
1900, 0, -1,-1,"Testing 123\nEdwardian script ITC", "Edwardian script ITC", 36.0,$000000,$FFFFFF, 5,0,0,0.0,0.0,false,true, 4, 4,$F88F48,0.50
"""
ColorBars.KillAudio.trim(0,-2000).ShowFrameNumber
CSV="MyFile.CSV"
RT_WriteFile(CSV,"%s",SSS) # Fountain requires CSV file, so write one.
Fountain(CSV)
EDIT: I'm not sure that all used fonts are standard windows, maybe Libre Office installed a few additional ones.
poisondeathray
8th September 2017, 14:03
PDR, does this assist at all ?
not sure, I am missing a few things for that script, I;ll have to test it later
EDIT: PDR, what you get for Chr(10) on your ver$ windows ?
chr(10) is a blank space
or did you mean chr($10) ? It's like a big plus sign
https://s26.postimg.org/z5zpqzf6x/chr_10.png (https://postimages.org/)
StainlessS
8th September 2017, 15:09
Thanx PDR, was just wondering how it treated newline [Chr(10), not $10].
StainlessS
9th September 2017, 09:12
BoxMask post #26, removed GScript/RT_Stats requirements. (just needs masktools v2)
StainlessS
9th September 2017, 19:28
Post #28 Fountain() script updated, added background Opacity control to CVS format. Extended demo a bit.
https://s26.postimg.cc/5fsfd4ol5/Fountain.jpg (https://postimages.cc/)
https://s26.postimg.cc/pokeclda1/Fountain.jpg (https://postimages.cc/)
PDR, I think I misinterpreted your comment when doing BoxMask thing, below equivalent to your script using RT_Stats RT_YInRngLocate.
#Parameters
#############################
txt="This is my text, DUDE"
sz=40
ft="arial"
x_pos=100
y_pos=100
bg_color=color_blue
bg_opacity=0.5
txt_color=color_yellow
hal_color=color_black
BW=6
BH=BW
#############################
colorbars(pixel_type="YV12").Killaudio
bl=Last.blankclip(Length=1, pixel_type="YV12").mt_lut("0") # pure Black (Luma=0)
txtmsk=bl.subtitle(txt,x=x_pos,y=y_pos, font=ft, text_color=color_white, halo_color=color_white,size=sz)
Bingo=txtmsk.RT_YInRangeLocate(n=0,Baffle=1,Lo=16,Hi=255,Prefix="Sub_") # Measure text incl halo
Assert(Bingo,"Coords Not Found")
x1=max(Sub_X-BW,0) x2=min(Sub_X+Sub_W+BW,Width) y1=max(Sub_Y-BH,0) y2=min(Sub_Y+Sub_H+BH,Height) # Box coords incl Border width and height
Rpn=RT_string("x %d >= x %d < & y %d >= & y %d < & 255 0 ?",x1,x2,y1,y2)
Msk=bl.BlankClip.mt_lutspa(relative=false,Yexpr=Rpn, chroma = "-128" )
Last.overlay(bl.BlankClip(color=bg_color), opacity=bg_opacity,Mask=Msk) # Background
subtitle(txt,x=x_pos,y=y_pos, font=ft, text_color=txt_color, halo_color=hal_color,size=sz)
return Last
Oops, above bug fix.
https://s26.postimg.cc/bkjxqggop/Dude.jpg (https://postimages.cc/)
StainlessS
10th September 2017, 01:47
RaffRiff,
A couple of comments, my editor uses CR+LF, your script copes correctly with LF only.
LSP should be 0, to switch on multi-line processing, setting to fontsize is perhaps not what you intended.
#LoadPlugin(pathBase + "AutoCrop\AutoCrop.dll") # I use Plugins
Function ReplaceStr(string s,String f,String r) {return RT_StrReplace(s,f,r)} # My version of your ReplaceStr
fontface="Arial Bold Italic"
fontsize=32
textcolor=color_yellow
halocolor=color_blue
padding=4
x_adj=6 ## fudge factor
y_adj=6
lsp=0 # Not sure if lsp=fontsize is intentional (additional line spacing, 0=process multiline [undefined = dont process multiline])
# BELOW REQUIRED IF avs text editor uses standard PC EOL format, ie carriage return, LineFeed [Chr(13)+Chr(10)].
msg="""
In the beginning the Universe was created.
This has made a lot of people very angry
and been widely regarded as a bad move.
"""
## next 2 lines needed only if using multiline style above
msg=ReplaceStr(msg, Chr(13)+Chr(10), "\n").ReplaceStr(Chr(10), "\n") # Replace CR+LF or just LF
msg=MidStr(msg, 3) # Remove first line '\n'
#msg="""In the beginning the Universe was created.\nThis has made a lot of people very angry\nand been widely regarded as a bad move.""" # OR this format
orig=Colorbars(pixel_type="YV12").Killaudio
## /end user params
Blankclip(orig)
Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=$ffffff, halo_color=$ffffff,
\ lsp=lsp)
## (faster than mt_rectangle)
mt_expand.mt_expand.mt_expand
mt_expand.mt_expand.mt_expand
GrayScale
AutoCrop(mode=0, threshold=20)
## optional padding
AddBorders(padding, padding, padding, padding)
box=Last
#return box
bl2=Blankclip(box)
txt=bl2.Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=textcolor, halo_color=halocolor,
\ x=x_adj, y=y_adj, lsp=lsp)
#return txt
msk=bl2.Subtitle(msg,
\ font=fontface, size=fontsize,
\ text_color=$ffffff, halo_color=$ffffff,
\ x=x_adj, y=y_adj, lsp=lsp)
## expand mask to 0-255 range (there are prob. better ways to do this)
msk=msk.Levels(18, 1, 232, 0, 255, coring=false)
#return msk
## output example 1: center on screen
#orig.Overlay(txt, mask=msk,
#\ x=orig.Width/2-txt.Width/2,
#\ y=orig.Height/2-txt.Height/2)
## output example 2: bottom-right
orig.Overlay(txt, mask=msk,
\ x=orig.Width-txt.Width,
\ y=orig.Height-txt.Height)
return Last
EDIT: I have not bothered with CR only (which the occasional editor might use).
LF+CR should never be found (unless bad editor).
EDIT:
Multi-line text using "\n" is added in v2.57 and it is used if the lsp (line spacing) parameter is set. It sets the additional line space between two lines in 0.125 pixel units.
raffriff42
10th September 2017, 03:34
CR ("carriage return") is not important and can be ignored (I think).
LF ("line feed" aka "new line") is important.
It is my understanding that setting any value for lsp enables on multi-line processing (reading "\n" as a line break)
I set lsp=fontsize purely because I like the way it looks. (lsp<0 squeezes lines together, >0 spreads them apart)
I've been refining my code -- here's what I have now if anyone is interested (may need minor tweaks if not using AvisynthPlus)SubtitleAligned(<MESSAGE HERE>,
\ font="Arial Bold Italic", size=34,
\ text_color=color_yellow, halo_color=color_black,
\ align=5, justify=7, x=0, y=0, padding=0, showbox=0>0)
return Last
##################################
### [[Subtitle]] with improved alignment & optional padding
##
## @ text, first_frame, last_frame,
## font, size, text_color, halo_color,
## align, spc, font_width, interlaced - cf. Subtitle
##
## @ x, y - unlike Subtitle, act as offset to calculated <align> values
## @ font_angle - ignored
## @ lsp - cf. Subtitle except default=<size> ('\n'-style multiline always enabled)
## @ justify - paragraph justification; 7=left, 8=centered, 9=right; default 7
## (only applies to multi-line text; else no affect)
## @ padding - additional margin around text; minimum 2, default 2
## @ showbox - if true, make the bounding box visible
##
function SubtitleAligned(
\ clip C, string text,
\ int "x", int "y",
\ int "first_frame", int "last_frame",
\ string "font", float "size",
\ int "text_color", int "halo_color",
\ int "align", int "spc", int "lsp",
\ float "font_width", float "font_angle",
\ bool "interlaced",
\ int "justify", int "padding",
\ bool "showbox")
{
x = Default(x, 0)
y = Default(y, 0)
first_frame = Default(first_frame, 0)
last_frame = Default(last_frame, C.Framecount-1)
font = Default(font, "Arial")
size = Default(size, 18.0)
text_color = Default(text_color, $ffff00)
halo_color = Default(halo_color, $0)
align = Default(align, 7)
justify = Default(justify, 7)
spc = Default(spc, 0)
lsp = Default(lsp, Round(size))
font_width = Default(font_width, 0.0)
interlaced = Default(interlaced, false)
justify = ((FindStr(text, Chr(10))==0) && (FindStr(text, "\n")==0))
\ ? align : justify
justify = (justify==1) || (justify==4) ? 7
\ : (justify==2) || (justify==5) ? 8
\ : (justify==3) || (justify==6) ? 9
\ : justify
padding = Max(2, Default(padding, 2))
showbox = Default(showbox, false)
## handle multiline strings;
## remove leading newline if present
text = ReplaceStr(text, Chr(13), "")
text = (FindStr(text, Chr(10))==1) ? MidStr(text, 2) : text
text = ReplaceStr(text, Chr(10), "\n")
Blankclip(C, pixel_type="YV12")
Subtitle(text,
\ font=font, size=size,
\ text_color=$ffffff, halo_color=$ffffff,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
mt_expand.mt_expand.mt_expand
mt_expand.mt_expand.mt_expand
GrayScale
AutoCrop(mode=0, threshold=20)
AddBorders(padding, padding, padding, padding)
B = Blankclip(Last, pixel_type="RGB32")
#return Last
## Shift factors - fine tune margins/centering (HACK)
## left, center, right
x_adj = (align==1 || align==4 || align==7) ? -6
\ : (align==2 || align==5 || align==8) ? -4
\ : [* align==3 || align==6 || align==9 *] -2
## bottom, middle, top
y_adj = (align==1 || align==2 || align==3) ? 6
\ : (align==4 || align==5 || align==6) ? 2
\ : [* align==7 || align==8 || align==9 *] -4
T = B.Subtitle(text,
\ first_frame=first_frame, last_frame=last_frame,
\ font=font, size=size,
\ text_color=text_color, halo_color=halo_color,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
T = T.Shift((justify==9?-1:1)*(padding + x_adj), padding + y_adj)
T = T.Trim(0, -1).Loop(-1)
#return T
M = B.Subtitle(text,
\ first_frame=first_frame, last_frame=last_frame,
\ font=font, size=size,
\ text_color=$ffffff, halo_color=$ffffff,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
M = M.Blur(0.7)
M = M.Shift((justify==9?-1:1)*(padding + x_adj), padding + y_adj)
M = (showbox)
\ ? M.Levels( 0, 1, 255, 64, 255-64, coring=false)
\ : M.Levels(18, 1, 232, 0, 255, coring=false)
M = M.Trim(0, -1).Loop(-1)
#return M
T = T.ResetMask.Mask(M)
#return T.ShowAlpha
R = C.ConvertToRGB32.LayerAligned(T, x=x, y=y, mask=M, align=align)
return (C.IsYUY2) ? R.ConvertToYUY2
\ : (C.IsYV24) ? R.ConvertToYV24
\ : R.ConvertToYV12
}
##################################
### [[Layer]] with support for <mask>, <opacity> and <align> parameters
##
## @ op, level, threshold, use_chroma - cf. Layer
## @ base, over - RGBA only (RGB32 etc)
## @ x, y - unlike Layer, act as offset to calculated <align> values
## @ mask - if supplied, set alpha channel of clip <over>
## @ opacity - if supplied, override <level> (range 0..1)
## @ align - @see [[Subtitle]] ("number pad notation")
##
function LayerAligned(clip base, clip over, string "op", int "level",
\ int "x", int "y", int "threshold", bool "use_chroma",
\ clip "mask", float "opacity", int "align")
{
Assert(IsRGB(base) && IsRGB(over) && HasAlpha(base) && HasAlpha(over),
\ "LayerAligned: 'base' and 'over' clips must be RGBA")
lvl = Default(level, 257)
opc = Default(opacity, Float(lvl)/257.0)
lvl = Round(257.0 * opc)
x = Default(x, 0)
y = Default(y, 0)
aln = Default(align, 7)
over = IsClip(mask)
\ ? over.ResetMask.Mask(mask)
\ : over
## right, center, left
x = (aln==3 || aln==6 || aln==9) ? x + base.Width - over.Width
\ : (aln==2 || aln==5 || aln==8) ? x + (base.Width/2) - (over.Width/2)
\ : x
## bottom, middle, top
y = (aln==1 || aln==2 || aln==3) ? y + base.Height - over.Height
\ : (aln==4 || aln==5 || aln==6) ? y + (base.Height/2) - (over.Height/2)
\ : y
return (lvl<1) ? base
\ : Layer(base, over, op, lvl, x, y, threshold, use_chroma)
}
##################################
### shift a clip up-down and left-right (with sub-pixel precision);
### this results in repeated edge pixels
##
function Shift(clip C, float offh, float offv)
{
C
BilinearResize(Width, Height, -offh, -offv, Width, Height)
return Last
}
StainlessS
10th September 2017, 11:21
WOW!, looks impressive script [not tried it yet].
CR ("carriage return") is not important and can be ignored (I think).
LF ("line feed" aka "new line") is important.
Your first script produced 'undefined character' characters at line end for me, where the Chr(13) chars lived. [square boxes seen in earlier posted characterset images].
[EDIT: Some editors may use only Chr(10) internally, stripping CR on load, and writing back to file both CR+LF on write,
with my editor (PSPad) I think it is configurable, but is set currently as it was defaulted on setup]
To be pedantic, LineFeed is Chr(10), whereas NewLine is whatever your editor uses at end of line (ie file storage), in my case Chr(13)+Chr(10).
EDIT: Undefined chars
https://s26.postimg.cc/iknmj7ywp/Boxes.jpg (https://postimages.cc/)
Yanak
10th September 2017, 11:54
It becomes more and more hard for me to follow you guys,
Tested last scrip proposed and it is indeed working nicely, great piece of work on this, only problem is once i start to test with large font sizes, like using 100 or more for font size with a message all in capital letters, a good part of the bottom text gets amputated, need then to play with padding & x,y options to adjust all this but it's nice already like this.
Thank a lot.
StainlessS
10th September 2017, 14:52
Yanak, try out the Fountain script, I think it should play nice (let me know if not, and I shall fix).
EDIT: Except for the last four args in CSV file, they are all Subtitle function args. The last four concern only the
background box, pixel size outside of text (BW, BH), Box color, and opacity when Overlay-ing the box.
StainlessS
10th September 2017, 16:33
Yanak, quick and dirty func to create CSV file where almost all CSV items identical (first_frame, Last_frame auto set, must give multi-line text strings)
Function MkFountainCSV(String CSV,Int FrmsPerSub,Float "X", Float "Y",String "Text",String "Font",
\ Float "Size",Int "Text_Color",Int "Halo_Color",Int "Align",Int "Spc",Int "Lsp",Float "Font_Width",Float "Font_Angle",
\ Bool "Interlaced",Bool "VCenter",Int "BackGround_W",Int "BackGround_H",Int "BackGround_Color",Float "BackGround_Opacity") {
/*
Make Fountain() CSV file, where only Text strings differ (ie fixed font, align etc).
FrmsPerSub = Number of frames per Subtitle.
*/
myName="MkFountainCSV: "
X=Default(X,-1.0) # -1.0 = Undefined
Y=Default(Y,-1.0) # -1.0 = Undefined
Text=Default(Text,"") # MUST SUPPLY MULTI-LINE TEXT EVEN THOUGH OPTIONAL ARG
Font=Default(Font,"Ariel") # "Ariel"
Size=Default(Size,-1.0) # -1.0 = 18.0
Text_Color=Default(Text_Color,-1) # -1 = $FFFF00
Halo_Color=Default(Halo_Color,-1) # -1 = $000000
Align=Default(Align,-1) # -1 = 7
Spc=Default(Spc,0) # 0 = normal
Lsp=Default(Lsp,-1) # -1 = Undefined
Font_Width=Default(Font_Width,0.0) # 0.0 = System Default
Font_Angle=Default(Font_Angle,0.0) # 0.0 = System Default
Interlaced=Default(Interlaced,false) # OFF
VCenter=Default(VCenter,True) # Default True
BackGround_W=Default(BackGround_W,0) # 0=OFF
BackGround_H=Default(BackGround_H,0) # 0=OFF
BackGround_Color=Default(BackGround_Color,$808080) # Grey
BackGround_Opacity=Default(BackGround_Opacity,0.5) # 50.0%
Assert(CSV!="",RT_String("%s Need a CSV file name",myName))
Lines=RT_TxtQueryLines(Text)
Assert(Lines>0,RT_String("%s Need a Multi-line [Chr(10)] separated list of text strings",myName))
CSV=RT_GetFullPathName(CSV)
RT_FileDelete(CSV)
Fmt="""%d,%d,%.3f,%.3f,"%s","%s",%.3f,%d,%d,%d,%d,%d,%.3f,%.3f,%s,%s,%d,%d,%d,%.3f"""
GSCript("""
GotLines=0
Prev_last=-1
for(i=0,Lines-1) {
T=RT_TxtGetLine(Text,i)
if(T!="") {
GotLines=GotLines+1
RT_DebugF("%d]='%s'",GotLines,T)
first_frame=Prev_Last + 1
last_frame=first_frame + FrmsPerSub - 1
RT_WriteFile(CSV,Fmt,
\ first_frame, (last_frame==0)?-1:last_frame,
\ X, Y,
\ T, Font,
\ Size, Text_Color, Halo_Color,
\ Align, Spc, Lsp,
\ Font_Width, Font_Angle,
\ Interlaced, VCenter,
\ BackGround_W,BackGround_H,BackGround_Color,BackGround_Opacity,
\ Append=true)
Prev_last=last_frame
}
}
""")
}
# Import("Fountain.avsi") # Containing Fountain func only, ie no client script.
Text="""
1) Something
2) Anything
3) Something Else
4) Pomegranates
5) Apples
6) Oranges
7) Pears
8) Grapes
9) Sausages
"""
TEST_CSV="Test.CSV"
MkFountainCSV(Test_CSV,100,Text=Text)
#MkFountainCSV(Test_CSV,100,Text=Text,Font="Times New Roman",Size=40,align=5,BackGround_W=6,BackGround_H=6,BackGround_Color=$0000FF,BackGround_Opacity=0.5)
ColorBars.KillAudio.ShowFrameNumber
Fountain(TEST_CSV)
Yanak
10th September 2017, 17:02
Hi,
Thank you very much, this said I'm getting some error messages about there is no function named RT_String using this one, not sure if i am doing something wrong or missed something, tried to load RT_Stats but it's apparently x86 dll, did not found a x64 version .
Will have to try later using MP_Pipeline directly in my x64 version of avisynth.
StainlessS
10th September 2017, 17:05
Requirements
Fountain(), http://forum.doom9.org/showthread.php?p=1817802#post1817802
Function taking a CSV file (Comma Separated Values), of Subtitle Arguements, prints Subtitles on frame.
Req, RT_Stats v2.0 LINK REMOVED.
Req, CallCmd.
Req, Masktools v2.0, Pinterf.
Req, Avs v2.6.
Sorry, no x64 version available.
Yanak
10th September 2017, 17:17
I was afraid it will be this answer, but will try later, or most probably tomorrow as i'm a bit short in time today, using Mp_Pipeline if i can get something in my x64 version.
Thanks again for all the efforts done with this guys, still think this could be made way easier if avisynth+ simply returned desired text input sizes based on font and font size + text itself using his already built-in functions for this, here it's a lot of efforts you guys are doing and i thank you all for that , really, but it could have been so simple and more efficient/faster if being directly part of avs+ to avoid a lot of headhache with all the nice scripts you guys worked on.
Will have to spend lot of time testing all this stuff, sadly I'm not expert as most of you when it comes to very complex scripts like here but will manage to get something working for my needs based on all the stuff published here.
Thanks again.
StainlessS
10th September 2017, 18:47
Yanak.
OK, I've knocked up a x64 dll, have checked all warnings due to x64 compile and saw nothing to be too concerned about however
I cannot test as I'm on XP32.
I also found/fixed a bug revealed due to font="" being written to CSV (meaning use "Arial").
v2.0. beta 11, 10 Sept 2017.
Bugfix, RT_DBaseReadCSV write fail on zero length CSV string.
See MediaFire or SendSpace below my sig, hope all goes well for you, good luck.
EDIT: Or here:- http://www.mediafire.com/file/dhrrngn3g4iov1r/RT_Stats_25%2626_dll_v2.00Beta11_20170910.zip
EDIT: Below via the previous posted script MkFountainCSV thing, but with align changed to 3
MkFountainCSV(Test_CSV,100,Text=Text,Font="Times New Roman",Size=40,align=3,BackGround_W=6,BackGround_H=6,BackGround_Color=$0000FF,BackGround_Opacity=0.5)
https://s26.postimg.cc/qo0zs44op/Something_Else.jpg (https://postimages.cc/)
https://s26.postimg.cc/cvmkwhdx5/Apples.jpg (https://postimages.cc/)
EDIT: You can just comment out the CallCmd() line near end of Fountain script, there is no x64 plug for thatr either.
raffriff42
11th September 2017, 02:23
WOW!, looks impressive script [not tried it yet].
Your first script produced 'undefined character' characters at line end for me, where the Chr(13) chars lived.That might be from having two Chr(13)'s in a row, or something like that. My second script removes all Chr(13)'s, please see if that works on your end.
Sadly, as Yanak notes, my implementation of PDR's idea fails with large font sizes, and I don't see a simple fix.
Anyway, even if the "bounding box" problem is solved, the next issue will be mixed font styles, or ...
something else that is already supported in AssRender, VSFilter etc
Yanak
11th September 2017, 10:58
@StainlessS:
Thanks a lot for all the efforts, managed to get it more or less working, had some "Grunt" error messages, it's another x86 plugin, but bypassed it on my testings, still need to find out a few things and test this deeply, will take me some time but will get it working.
Thanks again.
@raffriff42 :
I understand perfectly yeah, the main goal was to have a full control on subtitles and what you can also do once you know the height and width for them, only 2 variables available for the end user that will bring a lot of possibility once known, and this without having the need for external stuff as this is somewhat already built in avisynth as you found out , it could probably be improved to be more accurate in terms of finding the bounding boxes of a text like with some of the drawtext options seen here (https://msdn.microsoft.com/en-us/library/windows/desktop/dd162498(v=vs.85).aspx).
Here we saw that align parameters are not perfect due to how they are calculated to start with in the internal avisynth code, all those issues could be bypassed and we could get a total control on this if we simply had the accurate height and width of a desired text returned directly by avisynth.
It will then be possible to have perfectly aligned texts with the desired margin from the sides or bottom of the video and this totally automated in the end users scripts, then a lot of things could be done like drawboxes around the subtitles, backgrounds, and probably some other things, all this will be extremely simple once you get the accurate height and width of a text string returned like ffpmeg does with the "text_h" & "text_w" options giving the height and width of a rendered text.
Only 2 variables offering a lot of possibilities if known like in some other programs offering this, and i really don't see the need for external programs to get only this.
Anyways thanks a lot for the all the help you guys provided, for all the scripts you worked on, now i will take some time to explore all this, try to understand all this and get something done for my needs.
I remain convinced that such option should be part of the program itself, natively, but it's probably only me here, like i said i used this in ffmpeg, used this in php too and it offers lots of possibilities and full control on the things you do once you get those simple variables available, in my opinion this should be part of any program having text rendering as a feature, but nothing i can do for this nor code it myself as being a noob in this domain, maybe I'll try to put a request on the github project page one of those days but not much hope on this.
The subject can now be closed, thanks again for all the help guys.
StainlessS
11th September 2017, 14:51
Sorry Yanak, forgot about Grunt requirement, (avs+ has built-in GSCript, not sure if you have to comment out GScript("""...""") stuff though.
Shall make CallCmd optional, ie if present then delete temp DBase on clip closure, else just leave it for user to delete.
Raff, I re-installed XP32 not so long ago, I perhaps previously used to set PsPad to use LF only (Unix style EOL) instead of default CR+LF (DOS style),
[CR only is MAC style EOL]. Have not done a totally clean re-install for years, usually from prev existing image. Anyway, set to Unix style LF only
and no problem, but we should really cope with DOS style too (as is default on Windows for raw text files, win notepad will create CR+LF text).
EDIT: Incidentally, RT_ReadTxtFromFile (or whatever its called), strips all sequences of CR+LF, LF+CR[BAD!!! should never be found], and CR and replaces them with single LF [Chr(10)]. You can have loads of fun if you can create a txt file containing CR+LF and LF+CR sequences, sends things like MS Word into weird berserk mode.
RT_TxtGetLine (or whatever its called), extracts a line from a LF separated multi-line string, and removes trailing LF from end of the line.
[EDIT: Not sure but I think it also interprets CR+LF as multi-line separator (probably CR only too)]
StainlessS
12th September 2017, 15:13
Raff, below have added HasAlpha() func, returning true (as false fails on avs standard)
Does below work correctly on AVS+ ?, is showing significant frame change on avs standard with HasAlpha always returning true (to make it work at all).
##################################
### [[Subtitle]] with improved alignment & optional padding
##
## @ text, first_frame, last_frame,
## font, size, text_color, halo_color,
## align, spc, font_width, interlaced - cf. Subtitle
##
## @ x, y - unlike Subtitle, act as offset to calculated <align> values
## @ font_angle - ignored
## @ lsp - cf. Subtitle except default=<size> ('\n'-style multiline always enabled)
## @ justify - paragraph justification; 7=left, 8=centered, 9=right; default 7
## (only applies to multi-line text; else no affect)
## @ padding - additional margin around text; minimum 2, default 2
## @ showbox - if true, make the bounding box visible
##
function SubtitleAligned(
\ clip C, string text,
\ int "x", int "y",
\ int "first_frame", int "last_frame",
\ string "font", float "size",
\ int "text_color", int "halo_color",
\ int "align", int "spc", int "lsp",
\ float "font_width", float "font_angle",
\ bool "interlaced",
\ int "justify", int "padding",
\ bool "showbox")
{
x = Default(x, 0)
y = Default(y, 0)
first_frame = Default(first_frame, 0)
last_frame = Default(last_frame, C.Framecount-1)
font = Default(font, "Arial")
size = Default(size, 18.0)
text_color = Default(text_color, $ffff00)
halo_color = Default(halo_color, $0)
align = Default(align, 7)
justify = Default(justify, 7)
spc = Default(spc, 0)
lsp = Default(lsp, Round(size))
font_width = Default(font_width, 0.0)
interlaced = Default(interlaced, false)
justify = ((FindStr(text, Chr(10))==0) && (FindStr(text, "\n")==0))
\ ? align : justify
justify = (justify==1) || (justify==4) ? 7
\ : (justify==2) || (justify==5) ? 8
\ : (justify==3) || (justify==6) ? 9
\ : justify
padding = Max(2, Default(padding, 2))
showbox = Default(showbox, false)
## handle multiline strings;
## remove leading newline if present
text = ReplaceStr(text, Chr(13), "")
text = (FindStr(text, Chr(10))==1) ? MidStr(text, 2) : text
text = ReplaceStr(text, Chr(10), "\n")
Blankclip(C, pixel_type="YV12")
Subtitle(text,
\ font=font, size=size,
\ text_color=$ffffff, halo_color=$ffffff,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
mt_expand.mt_expand.mt_expand
mt_expand.mt_expand.mt_expand
GrayScale
AutoCrop(mode=0, threshold=20)
AddBorders(padding, padding, padding, padding)
B = Blankclip(Last, pixel_type="RGB32")
#return Last
## Shift factors - fine tune margins/centering (HACK)
## left, center, right
x_adj = (align==1 || align==4 || align==7) ? -6
\ : (align==2 || align==5 || align==8) ? -4
\ : [* align==3 || align==6 || align==9 *] -2
## bottom, middle, top
y_adj = (align==1 || align==2 || align==3) ? 6
\ : (align==4 || align==5 || align==6) ? 2
\ : [* align==7 || align==8 || align==9 *] -4
T = B.Subtitle(text,
\ first_frame=first_frame, last_frame=last_frame,
\ font=font, size=size,
\ text_color=text_color, halo_color=halo_color,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
T = T.Shift((justify==9?-1:1)*(padding + x_adj), padding + y_adj)
T = T.Trim(0, -1).Loop(-1)
#return T
M = B.Subtitle(text,
\ first_frame=first_frame, last_frame=last_frame,
\ font=font, size=size,
\ text_color=$ffffff, halo_color=$ffffff,
\ align=justify, spc=spc, lsp=lsp,
\ font_width=font_width, interlaced=interlaced)
M = M.Blur(0.7)
M = M.Shift((justify==9?-1:1)*(padding + x_adj), padding + y_adj)
M = (showbox)
\ ? M.Levels( 0, 1, 255, 64, 255-64, coring=false)
\ : M.Levels(18, 1, 232, 0, 255, coring=false)
M = M.Trim(0, -1).Loop(-1)
#return M
T = T.ResetMask.Mask(M)
#return T.ShowAlpha
R = C.ConvertToRGB32.LayerAligned(T, x=x, y=y, mask=M, align=align)
return (C.IsYUY2) ? R.ConvertToYUY2
\ : (C.IsYV24) ? R.ConvertToYV24
\ : R.ConvertToYV12
}
##################################
### [[Layer]] with support for <mask>, <opacity> and <align> parameters
##
## @ op, level, threshold, use_chroma - cf. Layer
## @ base, over - RGBA only (RGB32 etc)
## @ x, y - unlike Layer, act as offset to calculated <align> values
## @ mask - if supplied, set alpha channel of clip <over>
## @ opacity - if supplied, override <level> (range 0..1)
## @ align - @see [[Subtitle]] ("number pad notation")
##
function LayerAligned(clip base, clip over, string "op", int "level",
\ int "x", int "y", int "threshold", bool "use_chroma",
\ clip "mask", float "opacity", int "align")
{
Assert(IsRGB(base) && IsRGB(over) && HasAlpha(base) && HasAlpha(over),
\ "LayerAligned: 'base' and 'over' clips must be RGBA")
lvl = Default(level, 257)
opc = Default(opacity, Float(lvl)/257.0)
lvl = Round(257.0 * opc)
x = Default(x, 0)
y = Default(y, 0)
aln = Default(align, 7)
over = IsClip(mask)
\ ? over.ResetMask.Mask(mask)
\ : over
## right, center, left
x = (aln==3 || aln==6 || aln==9) ? x + base.Width - over.Width
\ : (aln==2 || aln==5 || aln==8) ? x + (base.Width/2) - (over.Width/2)
\ : x
## bottom, middle, top
y = (aln==1 || aln==2 || aln==3) ? y + base.Height - over.Height
\ : (aln==4 || aln==5 || aln==6) ? y + (base.Height/2) - (over.Height/2)
\ : y
return (lvl<1) ? base
\ : Layer(base, over, op, lvl, x, y, threshold, use_chroma)
}
##################################
### shift a clip up-down and left-right (with sub-pixel precision);
### this results in repeated edge pixels
##
function Shift(clip C, float offh, float offv)
{
C
BilinearResize(Width, Height, -offh, -offv, Width, Height)
return Last
}
MESSAGE_HERE="""
Once upon a time,
in a land far far away.
"""
ColorBars(pixel_type="YV24").KillAudio.trim(0,-2000).ShowFrameNumber
Org=Last
SubtitleAligned(MESSAGE_HERE,
\ font="Arial Bold Italic", size=34,
\ text_color=color_yellow, halo_color=color_black,
\ align=5, justify=7, x=0, y=0, padding=0, showbox=0>0)
D=ClipDelta(Last,Org)
DD=ClipDelta(Last,Org,true)
Top=Stackhorizontal(Sub(Org,"Src"),Sub(Last,"Result"))
Bot=Stackhorizontal(Sub(D,"Diff") ,Sub(DD,"Diff Amp'ed") )
Return StackVertical(Top,Bot).ConvertToYV12
Function Sub(clip c,string Tit,Bool "ShowFrameNo",int "first_frame", int "last_frame",string "font",float "size",int "text_color",
\ int "halo_color",int "align",int "spc",float "font_width",float "font_angle",Int "BackColor") {
/*
Stack Overhead Subtitle Text, with optional FrameNumber shown
http://forum.doom9.org/showthread.php?p=1813402#post1813402
Title bar is Round(size+2) pixels hi (default 20).
Dont use align=4,5,6, better use 1,2,3,7,8,or 9.
*/
ShowFrameNo=Default(ShowFrameNo,False) first_frame=Default(first_frame,0) last_frame=Default(last_frame,c.FrameCount-1)
font=default(font,"Ariel") size=Default(size,18.0) text_color=Default(text_color,$00FFFF00)
halo_color=Default(halo_color,$00000000) align=default(align,7) spc=Default(spc,0)
font_width=Default(font_width,0) font_angle=Default(font_angle,0.0) BackColor=Default(BackColor,$00000000)
c.BlankClip(height=round(size+2.0),Color=BackColor)
(ShowFrameNo)
\ ? ScriptClip("""Subtitle(String(current_frame,"%.0f] ")+"""+Chr(34)+Tit+Chr(34)+String(first_frame,",first_frame=%.0f")+
\ String(last_frame,",last_frame=%.0f,font=")+Chr(34)+font+Chr(34)+String(size,",size=%.3f")+String(text_color,",text_color=%.0f")+
\ String(halo_color,",halo_color=%.0f")+String(align,",align=%.0f")+String(spc,",spc=%.0f")+String(font_width,",font_width=%.3f")+
\ String(font_angle,",font_angle=%.3f)"))
\ : Subtitle(Tit,first_frame=first_frame,last_frame=last_frame,font=font,size=size,text_color=text_color,halo_color=halo_color,align=align,
\ spc=spc,font_width=font_width,font_angle=font_angle)
Return StackVertical(c).AudioDubEx(c)
}
# Return Clip Difference of input clips (amp==true = Amplified, show==true = show background)
Function ClipDelta(clip clip1,clip clip2,bool "amp",bool "show") {
amp=Default(amp,false)
show=Default(show,false)
c2=clip1.levels(128-32,1.0,128+32,128-32,128+32).greyscale()
c1=clip1.subtract(clip2)
c1=(amp)?c1.levels(127,1.0,129,0,255):c1
return (show)?c1.Merge(c2):c1
}
# STUFF to make it work on AVS standard # UnComment on AVS Standard
#Function ReplaceStr(string s,String f,String r) {return RT_StrReplace(s,f,r)} # My version of your ReplaceString
#Function HasAlpha(clip c) {return True }
https://s26.postimg.cc/5j08mhg8p/Diff.jpg (https://postimages.cc/)
EDIT: Change end of Foundtain.avs script to below to show differencing stuff (EDIT: only box/subtitle changed)
ColorBars(pixel_type="YV24").KillAudio.trim(0,-2000).ShowFrameNumber
Org=Last # EDIT: Oops, moved to here
CSV="MyFile.CSV"
RT_WriteFile(CSV,"%s",SSS) # Fountain requires CSV file, so write one.
Fountain(CSV)
D=ClipDelta(Last,Org)
DD=ClipDelta(Last,Org,true)
Top=Stackhorizontal(Sub(Org,"Src"),Sub(Last,"Result"))
Bot=Stackhorizontal(Sub(D,"Diff") ,Sub(DD,"Diff Amp'ed") )
Return StackVertical(Top,Bot).ConvertToYV12
Function Sub(clip c,string Tit,Bool "ShowFrameNo",int "first_frame", int "last_frame",string "font",float "size",int "text_color",
\ int "halo_color",int "align",int "spc",float "font_width",float "font_angle",Int "BackColor") {
/*
Stack Overhead Subtitle Text, with optional FrameNumber shown
http://forum.doom9.org/showthread.php?p=1813402#post1813402
Title bar is Round(size+2) pixels hi (default 20).
Dont use align=4,5,6, better use 1,2,3,7,8,or 9.
*/
ShowFrameNo=Default(ShowFrameNo,False) first_frame=Default(first_frame,0) last_frame=Default(last_frame,c.FrameCount-1)
font=default(font,"Ariel") size=Default(size,18.0) text_color=Default(text_color,$00FFFF00)
halo_color=Default(halo_color,$00000000) align=default(align,7) spc=Default(spc,0)
font_width=Default(font_width,0) font_angle=Default(font_angle,0.0) BackColor=Default(BackColor,$00000000)
c.BlankClip(height=round(size+2.0),Color=BackColor)
(ShowFrameNo)
\ ? ScriptClip("""Subtitle(String(current_frame,"%.0f] ")+"""+Chr(34)+Tit+Chr(34)+String(first_frame,",first_frame=%.0f")+
\ String(last_frame,",last_frame=%.0f,font=")+Chr(34)+font+Chr(34)+String(size,",size=%.3f")+String(text_color,",text_color=%.0f")+
\ String(halo_color,",halo_color=%.0f")+String(align,",align=%.0f")+String(spc,",spc=%.0f")+String(font_width,",font_width=%.3f")+
\ String(font_angle,",font_angle=%.3f)"))
\ : Subtitle(Tit,first_frame=first_frame,last_frame=last_frame,font=font,size=size,text_color=text_color,halo_color=halo_color,align=align,
\ spc=spc,font_width=font_width,font_angle=font_angle)
Return StackVertical(c).AudioDubEx(c)
}
# Return Clip Difference of input clips (amp==true = Amplified, show==true = show background)
Function ClipDelta(clip clip1,clip clip2,bool "amp",bool "show") {
amp=Default(amp,false)
show=Default(show,false)
c2=clip1.levels(128-32,1.0,128+32,128-32,128+32).greyscale()
c1=clip1.subtract(clip2)
c1=(amp)?c1.levels(127,1.0,129,0,255):c1
return (show)?c1.Merge(c2):c1
}
EDIT: OK, changing to below removes the obvious non amp'ed differences, so must probably work ok on avs+.
ColorBars(pixel_type="RGB32").KillAudio.trim(0,-2000).ShowFrameNumber
Org=Last
SubtitleAligned(MESSAGE_HERE,
\ font="Arial Bold Italic", size=34,
\ text_color=color_yellow, halo_color=color_black,
\ align=5, justify=7, x=0, y=0, padding=0, showbox=0>0)
ConvertToRGB32 # avoid 'image formats dont match'
# etc
raffriff42
12th September 2017, 20:47
StainlessS, yes the script runs and looks the same on AVS+. The differences in the PLUGE (http://avisynth.nl/index.php/Colorbars#PLUGE) are because the I, Q and -4IRE bars are slightly clipped when converting to 0-255 -- this is normal. That's why using RGB bars fixes the problem. I'm not sure about the differences around the frame numbers.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.