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. Domains: forum.doom9.org / forum.doom9.net / forum.doom9.se |
|
|
#1 | Link |
|
Registered User
Join Date: Jan 2006
Posts: 1,869
|
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 |
|
|
|
|
|
#2 | Link |
|
Registered User
Join Date: Jan 2006
Posts: 1,869
|
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. |
|
|
|
|
|
#3 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#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). |
|
|
|
|
|
#7 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#10 | Link |
|
Registered User
Join Date: Jan 2006
Posts: 1,869
|
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. |
|
|
|
|
|
#11 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#12 | Link | |
|
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,442
|
Quote:
|
|
|
|
|
|
|
#13 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#14 | Link |
|
Registered User
Join Date: Jan 2006
Posts: 1,869
|
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.
|
|
|
|
|
|
#15 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#16 | Link |
|
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,442
|
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. |
|
|
|
|
|
#17 | Link |
|
Registered User
Join Date: Nov 2009
Posts: 2,375
|
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 |
|
|
|
|
|
#18 | Link |
|
Registered User
Join Date: Jan 2006
Posts: 1,869
|
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! |
|
|
|
|
|
#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;-)
|
|
|
|
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
|
|