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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 12th October 2011, 01:37   #1  |  Link
jmac698
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
jmac698 is offline   Reply With Quote
Old 12th October 2011, 05:24   #2  |  Link
jmac698
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.
jmac698 is offline   Reply With Quote
Old 15th October 2011, 20:03   #3  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 15th October 2011, 22:39   #4  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
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).
tin3tin is offline   Reply With Quote
Old 15th October 2011, 23:42   #5  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Ahh, thanks. I've done those two in assembly before There's an integer way to draw lines. I might look into layer...
jmac698 is offline   Reply With Quote
Old 15th October 2011, 23:44   #6  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Here's a quick fix, change this line:
Code:
opacity==256?mt_lutxyz(c, mask, last,expr="y 255 = z x ?"):mt_merge(c, last, mask, luma=true)
For a background, just start with a blankclip.
jmac698 is offline   Reply With Quote
Old 16th October 2011, 00:17   #7  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 23rd October 2011, 05:29   #8  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
It's updated, with a bunch of new features.
jmac698 is offline   Reply With Quote
Old 25th October 2011, 23:41   #9  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
bump
ver 0.4
jmac698 is offline   Reply With Quote
Old 26th October 2011, 00:00   #10  |  Link
jmac698
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.
jmac698 is offline   Reply With Quote
Old 26th October 2011, 09:52   #11  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 26th October 2011, 12:19   #12  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by Dogway View Post
function BoxMask(clip clip, int "x1", int "y1", int "x2", int "y2", bool "show"){
...
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 ?")}
Can't you do it all with a single call to mt_lutspa with an expression which tests to see if x and y are within the relevant ranges?
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 26th October 2011, 12:53   #13  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 26th October 2011, 14:07   #14  |  Link
jmac698
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 ?")
mode="absolute" means that, if you use x/y in the yexpr, it's the coordinates from x=(0,width-1) and y=(0, height-1).
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.
jmac698 is offline   Reply With Quote
Old 26th October 2011, 16:48   #15  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 26th October 2011, 17:04   #16  |  Link
Gavino
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.
__________________
GScript and GRunT - complex Avisynth scripting made easier

Last edited by Gavino; 26th October 2011 at 17:25.
Gavino is offline   Reply With Quote
Old 26th October 2011, 18:22   #17  |  Link
Dogway
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
Dogway is offline   Reply With Quote
Old 26th October 2011, 22:25   #18  |  Link
jmac698
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!
jmac698 is offline   Reply With Quote
Old 3rd November 2011, 09:09   #19  |  Link
redfordxx
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;-)
redfordxx is offline   Reply With Quote
Old 3rd November 2011, 13:12   #20  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
Because I'm not just creating an image, I want to draw on top of an existing image. If you just want to create an image, of course you can skip the rest.
jmac698 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 05:47.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.