Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
12th October 2011, 01:37 | #1 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
New Script: Drawrect 0.6
Another one of my utility functions.
Code:
#Drawrect 0.6 by jmac698 #a script to draw rectangles on top of existing video or create masks #requires masktools v2a45+ (mode in lutspa) and yv12 video #0.6: Added even faster option, bool "chroma", simplified code #0.5: Speedup and simplification (thanks Gavino, yet again), new function createrect, improved code #0.4: Added calculated named colors, removed old system #0.3: Added fully opaque with opacity=256, now default. Fixed bugs. Added colors. Refactored. Outline option. # Bugs: When opacity=256, the color edges are not merged, #todo: finish deepcolor support, more shapes #Usage: #createrect(clip c, int x1, int y1, int x2, int y2, int "foreclr" (255), int "backclr" (0), bool "filled" (true), bool "chroma" (false)) This is meant to create a simple rect mask #drawrect(clip c, int x1, int y1, int x2, int y2, int foreclr, int "opacity" (256), bool "filled" (true), bool "chroma" (false)) This is meant to draw on existing video #opacity=256 for fully opaque colorbars(pixel_type="YV12") createrect(400,400,419,419)#Great for making masks, a square with luma=255 and 0 elsewhere. Note that chroma is untouched by default! #Now use drawrect to add more shapes onto the first mask drawrect(1,1,150,200,named_color("cyn"), filled=false)#a cyan square drawrect(1,40,300,40,named_color("red"))#a red horizontal line (notice at y=41 the color overwrites the background) drawrect(280,300,319,340,$FF8080,opacity=127)#transparent white rectangle drawrect(-10,-10,5,5,$B08080)#test behavior with offscreen coordinates function drawrect(clip c, int x1, int y1, int x2, int y2, int foreclr, int "opacity", bool "filled", bool "chroma"){ #A function to draw a filled rectangle into a YV12 clip, can also draw lines as (1,1,1,200,$7E8080): a vertical line 1 pixel wide from 1,1 to 1,200 #Note that chroma will be merged with the input clip; draw on mod 2 boundaries if you need to ensure the given pixel chroma #The opacity formula is (opacity*foreground+(255-opacity)*background+128)/256 #You can't draw 255 on black unless you use opacity=256, because opacity=255 gives output=254 #If create=true, it just draws a single rectangle #chroma=true (default) to process chroma. This function is meant to draw colored rect's on video, so defaults to true. #(It can also build masks with more than one rect) filled=default(filled, true) opacity=default(opacity,256) chroma=default(chroma, true) y=getword(foreclr, 2)#byte=2 (n*65536), wordsize=1 u=getword(foreclr, 1) v=getword(foreclr, 0) #"x>=xl & x<=xh & y>=yl & y<= yh ? Y : 16" y is the coordinate y, Y is a variable which is substituted as a number in the expression #"x x1 >= & x xh <= y yl >= & y yh <= & & Y 16 ?" xl=min(x1, x2)#sort the coordinates xh=max(x1, x2) yl=min(y1, y2) yh=max(y1, y2) xl2=ceil(xl/2)#chroma coordinates in YV12 are half, ensure they are just larger than luma size xh2=ceil(xh/2) yl2=ceil(yl/2) yh2=ceil(yh/2) m=opacity==256?255:256 chromamode=chroma?3:1 drawstry2=drawstr(y, m) drawstru2=drawstr(u, m) drawstrv2=drawstr(v, m) drawstrm=buildrectexp(xl, yl, xh, yh, opacity, 0, filled) drawstrmuv=buildrectexp(xl2, yl2, xh2, yh2, opacity, 0, filled) mask=mt_lutspa(c, mode="absolute", yexpr=drawstrm, uexpr=drawstrmuv, vexpr=drawstrmuv, u=chromamode, v=chromamode) mt_lutxy(c, mask, yexpr=drawstry2, uexpr=drawstru2, vexpr=drawstrv2, u=chromamode, v=chromamode) } function createrect(clip c, int x1, int y1, int x2, int y2, int "foreclr", int "backclr", bool "filled", bool "chroma"){ #chroma=true (default) to process chroma. This function is meant to draw white rect's for masks, so defaults to false. foreclr=default(foreclr, $FF8080) backclr=default(backclr, $008080) filled=default(filled, true) chroma=default(chroma, false) yf=getword(foreclr, 2)#byte=2 (n*65536), wordsize=1 uf=getword(foreclr, 1) vf=getword(foreclr, 0) yb=getword(backclr, 2) ub=getword(backclr, 1) vb=getword(backclr, 0) xl=min(x1, x2)#sort the coordinates xh=max(x1, x2) yl=min(y1, y2) yh=max(y1, y2) xl2=ceil(xl/2)#chroma coordinates in YV12 are half, ensure they are just larger than luma size xh2=ceil(xh/2) yl2=ceil(yl/2) yh2=ceil(yh/2) chromamode=chroma?3:1 drawstry=buildrectexp(xl, yl, xh, yh, yf, yb, filled) drawstru=buildrectexp(xl2, yl2, xh2, yh2, uf, ub, filled) drawstrv=buildrectexp(xl2, yl2, xh2, yh2, vf, vb, filled) mt_lutspa(c, mode="absolute", yexpr=drawstry, uexpr=drawstru, vexpr=drawstrv, u=chromamode, v=chromamode) } function drawstr(int clr, int m) { return string(clr)+ " y * "+string(m)+" y - x * + "+string(m)+" /" } function buildrectexp(int xl, int yl, int xh, int yh, int clrfore, int clrback, bool filled){ #if x=x1 or x=x2 and y>=y1 and y<=y2 or y=y1 or y=y2 and x>=x1 and x<=x2 #x x1 = x x2 = or y y1 >= y y2 <= and and y y1 = y y2 = or x x1 >= x x2 <= and and or filled?"x "+string(xl)+" >= x "+string(xh)+" <= & y "+string(yl)+" >= y "+string(yh)+" <= & & "+string(clrfore)+" "+string(clrback)+" ?" \ :"x "+string(xl)+" = x "+string(xh)+" = | y "+string(yl)+" >= y "+string(yh)+" <= & & y "+ \ string(yl)+" = y "+string(yh)+" = | x "+string(xl)+" >= x "+string(xh)+" <= & & | "+string(clrfore)+" "+string(clrback)+" ?" } function named_color(string color, string "colorspace", float "luma", float "sat", bool "deepcolor") { #calculate the named color in yuv with specificed saturation and luminance color=lcase(color) colorspace=default(colorspace, "rec601") luma=default(luma, .75) sat=default(sat, .75) deepcolor=default(deepcolor, false) #Define in rgb, it's easiest colorrgb="111" colorrgb=color=="yel"||color=="yellow"?"110":colorrgb colorrgb=color=="cyn"||color=="cyan"?"011":colorrgb colorrgb=color=="grn"||color=="green"?"010":colorrgb colorrgb=color=="mag"||color=="magenta"?"101":colorrgb colorrgb=color=="red"?"100":colorrgb colorrgb=color=="blu"||color=="blue"?"001":colorrgb colorrgb=color=="blk"||color=="black"?"000":colorrgb r=midstr(colorrgb, 1, 1)=="1"?1:0 g=midstr(colorrgb, 2, 1)=="1"?1:0 b=midstr(colorrgb, 3, 1)=="1"?1:0 #Need to be more flexible. -I=(-.956295,.272558,1.104744) kr601=.299 kg601=.587 kb601=.114 kr709=.2125 kg709=.7154 kb709=.0721 y=colorspace=="rec601"?kr601*r+kg601*g+kb601*b:kr709*r+kg709*g+kb709*b pb=colorspace=="rec601"?(b-y)/(1-kb601):(b-y)/(1-kb709) pr=colorspace=="rec601"?(r-y)/(1-kr601):(r-y)/(1-kr709) scale=deepcolor?65536:256 yscale=deepcolor?219*219:219*luma cscale=deepcolor?112*112:112*sat round(y*yscale+scale/16)*scale*scale+round(pb*cscale+scale/2)*scale+round(pr*cscale+scale/2) } function hexbyte(int n) { #This function returns the lower byte of n as a 2 digit hex string. #For example, hex(257)="01". n=n%256 h=floor(n/16) l=n%16 s1=h>9?h+65-10:h+48 s2=l>9?l+65-10:l+48 chr(s1)+chr(s2) } function hex(int n){ #returns 3 byte hex string d2=floor(n/65536) n=n-d2*65536 d1=floor(n/256) n=n-d1*256 hexbyte(d2)+hexbyte(d1)+hexbyte(n) } function getword(int n, int p, int "size"){ #Get word p of size size from n, limited to p=(0,2) #Warning: due to a bug in avisynth 2.6a3, p=2 and size=2 gives wrong answrs size=default(size, 1) f=pow(2,8*size*2) p2=floor(n/f) n=n-p2*f f=pow(2,8*size*1) p1=floor(n/f) n=n-p1*f p0=n int(p==0?p0:p==1?p1:p2) } Last edited by jmac698; 9th November 2011 at 19:26. Reason: Updated |
12th October 2011, 05:24 | #2 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
Ugh, bug upon bug... first of all, avspmod 2.05 doesn't show the correct YUV values in the status line.
Now that I'm using 2.20 which works, I find that there's a bug in my function, due to the way mt_merge works. It calculates (x*256+128)/256 and when x=255 (when drawing a white line), I'm getting 254 back, so it's NOT drawing the correct colors. I'll have to investigate later. |
15th October 2011, 20:03 | #3 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
Yes, I was just about to tell you that, but looks you already realised. Can I suggest you a few additions? for example the ability to make white and black colors, if I write $ffffff then I get 235, and sometimes I may want 255 so I can use it as a mask. For the same reason it would be good if you could also add a background color, that is empty (bypass to clip) or some color like black for masks. Thanks for these tools!
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
15th October 2011, 22:39 | #4 | Link |
Registered User
Join Date: Mar 2005
Posts: 366
|
For inspiration I like to mention some drawing scrips I did some time ago(lines and circles):
http://forum.doom9.org/showthread.php?t=158194
__________________
DVD slideshow GUI(Freeware). |
16th October 2011, 00:17 | #7 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
It takes some loading time but thanks it works! for background I will be using mt_lut("0",u=-128,v=-128), I want to switch everything related to layer, overlay, and blankclip to masktools, there comes my interest in your tools
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
26th October 2011, 00:00 | #10 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
dogway,
bad news, this approach is incredibly slow, for more than a few shapes. It's building big tables for every call at initialization time. Back to blankclip and layer (avoid overlay, too many conversions). edit ok, anyone have a suggestion for a better way to draw shapes in script, or am I going to have to write a plugin? I don't have time to write a plugin now though. If I had to draw a shape, I would have to use layer to draw 4 lines. The docs are a little sketchy, talking about "these only seem to work in yuy2". Last edited by jmac698; 26th October 2011 at 00:23. |
26th October 2011, 09:52 | #11 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
Well I have been using the next code relating to boxes, I just thought your procedures were more "right to the spot", orthodox to call it some way.
function BoxMask(clip clip, int "x1", int "y1", int "x2", int "y2", bool "show"){ w=clip.width() h=clip.height() x1=default(x1,0) y1=default(y1,0) x2=default(x2,w) y2=default(y2,h) show=default(show, false) clip.mt_lut("255",u=-128,v=-128).crop(w-(x2-x1),h-(y2-y1),0,0) AddBorders(x1,y1,w,h).crop(0,0,w,h) show?mt_merge(clip,last,mt_lut(" x 17 < 0 x 2 / - ?"),u=-128,v=-128):mt_lut(" x 17 < 0 x ?")}
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
26th October 2011, 12:19 | #12 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
|
|
26th October 2011, 12:53 | #13 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
I don't know... I don't understand mt_lutspa, even the example provided doesn't work for me.
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
26th October 2011, 14:07 | #14 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
It's easy
Code:
mt_lutspa(c, mode="absolute", yexpr="x 0 >= x 91 <= & y 0 >= y 239 <= & & 180 16 ?") Next is just what to draw, if x>=0 & x<=91 & y>=0 & y<=239 then 180 else 16 Which fills in a box from (0,0)-(91, 239) with 180. The outside of the box is 16. And actually Gavino gave me an idea, if I could collect all the shapes at once, I can make a huge expression to plot them all at the same time, which would be faster The problem is overlap, I don't know how it would react to that. |
26th October 2011, 16:48 | #15 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
yeeeeee, so cool, this is very straight forward. Now that it works it's easy to understand. But in the documentation the code provided didn't work:
mt_lutspa(relative = true, "x y + 256 * 2 /", chroma = "128" )
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
26th October 2011, 17:04 | #16 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
The example is wrong, it should be:
mt_lutspa(relative = true, expr="x y + 256 * 2 /", chroma = "128" ) EDIT: The latest documentation has the example correct. The earlier one possibly worked before the parameter order got changed in v43. Last edited by Gavino; 26th October 2011 at 17:25. |
26th October 2011, 18:22 | #17 | Link |
Registered User
Join Date: Nov 2009
Posts: 2,361
|
Yes, I found it, it was a bit hidden (masktools-v2.0a48.zip\masktools\documentation) so I was using another old html from somewhere. Thanks!
__________________
i7-4790K@Stock::GTX 1070] AviSynth+ filters and mods on GitHub + Discussion thread |
26th October 2011, 22:25 | #18 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
I've asked manano to update his webpage, it's happened many times that people are confused by the outdated documentation.
And beware of using expr with chroma="process", because the chroma resolution is different, the expression will be 2x bigger than you are intending, for example the box, will have a double sized box in chroma with color=180, certainly not what you intend! |
3rd November 2011, 09:09 | #19 | Link |
Registered User
Join Date: Jan 2005
Location: Praha (not that one in Texas)
Posts: 863
|
Well I glanced on the script...I think you can do pretty much anything with one mt_lutspa call... so why all these lutxyz and merges...unless there is a lenght limit on expr in masktools;-)
|
|
|