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. |
|
|
#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 | |
| Display Modes | |
|
|