HDColorBars

From Avisynth wiki
Jump to: navigation, search

HDColorBars

#Attribution-ShareAlike 3.0

#Generate HD colorbars, arib_std_b28
#by jmac698, jan/2010, for Midzuki
#version 0.1.  
#Bugs/Limitations:
#Width of bars may not be totally accurate, especially e.g. section1 where width divisor of 7 doesn't add up.
#the color for plusI is not accurate, however -I is currently being used.
#only evaluated for 1080p.  Other sizes may not be of correct size of blocks, and
#also incorrect total size (as it's pieced together from blocks/sections).
#also framerate is 29.976, you can adjust this.  There is also some sound.
#to use: adjust GLOBAL definitions below for overall video parameters, then adjust choice
#to one of 3 options specified by the standard.
#also duration is fixed at about 3minutes
#also it's very slow, could be done with blankclip in block(), but ramp() still needs recursive

#Function summary
#pair(int y1,int y2,int w, int h, int d) - creates a pair of lines in YV12, with luminence Y1 and Y2
#loopstack(clip vid,int index,int end, string dir, string hfunc, string vfunc) - create a loop of 'count' over the function specified. 
#  The resulting videos are stacked.
#StrReplace(string base, string sought, string rep) - utility to help parse strings.  It replaces all occurences of a string.
#...some other utilities

#These values define full control over the video type generated
global fps=30000
global fps_denom=1001
global sr=48000
global ch=2

#pair - this works perfectly.  directly specify y1,y2,u,v (u=v=128 is grey)
function pair(int y1,int y2, int u, int v, int w, int h, int d) {
    #creates a clip with a pair of lines colored y1,y2 and common color u,v with width w and height h
    #stack horizontally (d=0) or vertically (d=1). eg d=0, y1|y2.  Each line is 1 pixel.  Output is YV12.
    l1=blankclip(pixel_type="YV12",width=w,height=h,fps=fps,fps_denominator=fps_denom,audio_rate=sr,channels=ch,length=720/4*30).ColorYUV(off_y=y1-16,off_u=u-128, off_v=v-128)
    l2=blankclip(pixel_type="YV12",width=w,height=h,fps=fps,fps_denominator=fps_denom,audio_rate=sr,channels=ch).ColorYUV(off_y=y2-16,off_u=u-128, off_v=v-128)
    d==1?stackvertical(l1,l2):stackhorizontal(l1,l2)
    pointresize(w,h)#two 1 pixel lines specified in direct YUV and resized
}

function loopstack(clip vid,int index,int end, string dir, string hfunc, string vfunc) {
    #generic for/next loop of hfunc/vfunc called with index as $i
    d=(dir=="v"||dir=="vertical")?1:0
    dir=(d==1)?"vertical":"horizontal"
    hfunc=StrReplace(hfunc,"$i","index")#string(index) doesn't update
    vfunc=StrReplace(vfunc,"$i","index")#select is slow
    #assert(false,hfunc)#shows first call to pair()
    d==1?index<end?Apply("stack"+dir,Eval(vfunc),loopstack(vid,index+1,end,dir,hfunc,vfunc)):Eval(vfunc): \
    index<end?Apply("stack"+dir,Eval(hfunc),loopstack(vid,index+1,end,dir,hfunc,vfunc)):Eval(hfunc)
}
   

Function StrReplace(string base, string sought, string rep)
	{
		pos = FindStr(base, sought)
		return (sought == "") || (pos == 0) \
			? base \
			: StrReplace( \
				LeftStr(base, pos - 1) + rep + \
				MidStr(base, pos + StrLen(sought)), \
				sought, rep)
	}
#YRamp: ramp luma from y1 to y2 (left to right) and color u,v, in a block (even) w, h
#potential bug: if w is odd, it will be widened to the nearest even amount (because of YV12), and final y2 will be +1
#   if you need an odd-width ramp, you will have to do this in another color space (or twice as big framesize later reduced)
#ie w=219, y1=16, y2=235 gives, a 220 wide video ending in y=235,236 in last two columns
#also special rounding is used, so that w=440, y1=16, y2=235 gives 440 wide video starting y=16,16,17,17....234,235,235.  This is not possible without round tie to zero!
Function YRamp(int y1,int y2, int u, int v, int w, int h) {
    yd=y2-y1#change in luma
    i=(float(yd)/(w-2))#change in luma per x, note -2 is to make end y 'longer' ie w=438, ends with 235,235 (actually 235.5)
    #this is an interesting case where round to zero on tie is better, as (0,.5,1,1.5)->(0,1,1,2) is out of range and too much total power, (0,0,1,1) is more correct
    j=int((w-1)/2)

    loopstack(blankclip,0,j,"h","pair(rnd(index*2*"+String(i)+"+16),rnd((index*2+1)*"+String(i)+"+16),"+String(u)+","+String(v)+",2,"+String(h)+",0)","pair(index*2+16,index*2+17,"+String(u)+","+String(v)+",48,4,0)") 
}	
Function Ramp(int w, int h) {
    YRamp(16, 235, 128, 128, w, h) 
}
#special round:  round towards 0 on tie; rnd(1.5)=1, rnd(-1.5)=-1
Function rnd(float i) {
    Return (frac(abs(i))==0.5) ? floorz(i) : round(i)
}
#special floor: floor towards 0; floorz(1.9)=0, floorz(-1.9)=-1
Function floorz(float i) {
    return sign(i)*floor(abs(i))
}
#parse color strings
Function yof(string c) {
    return int(value(midstr(c,1,3)))
}
Function uof(string c) {
    return int(value(midstr(c,5,3)))
}
Function vof(string c) {
    return int(value(midstr(c,9,3)))
}
#simple block of color w,h, color
Function block(string c, int w, int h) {
    w=(w%2)==1?w+1:w
    pair(yof(c),yof(c),uof(c),vof(c),int(w),h,0)
}
#Rec.709 values of color bars, to be used only for digital or hd signals
blkm2="012,128,128"
blk="016,128,128"
blkp2="020,128,128"
blkp4="025,128,128"
gry15="049,128,128"
gry40="104,128,128"
wht75="180,128,128"
wht100="235,128,128"
yel75="168,044,136"
cyn75="145,147,44"
grn75="134,063,052"
mag75="063,193,204"
red75="051,109,212"
blu75="028,212,120"
yel100="219,016,138"
cyn100="188,154,016"
red100="063,102,240"
blu100="032,240,118"
#need to check this, as -I is 16,158,95, document specified +I
plusi="016,158,095"
plusq="16,175,150" #used for SMPTE HD (ref?)

choice=plusi

	w=220*1
	d=0
	h=480
	u=10
	v=12
#Function Demos
#loopstack(clip vid,int index,int end, string dir, string hfunc, string vfunc)
#pair(127,128,u,v,2,48,0)
#loopstack(blankclip,1,360,"h","pair(index*2+16,index*2+17,"+String(u)+","+String(v)+",2,"+String(h)+",0)","pair(index*2+16,index*2+17,"+String(u)+","+String(v)+",48,4,0)") 
#YRamp(16,235,128,128,w,h)

a=1920 #or 1280
b=1080 #or 720
c=a*.75/7 #205 5/7
d=(a-.75*a)/2 #240
b1of12=b/12
b3of12=b*3/12
b7of12=b*7/12
c3of2=c*3/2
c5of6=c*5/6
c1of3=c*1/3

#section1
s1a=block(gry40,int(d),b7of12)
s1b=block(wht75,int(c),b7of12)
s1c=block(yel75,int(c),b7of12)
s1d=block(cyn75,int(c),b7of12)
s1e=block(grn75,int(c),b7of12)
s1f=block(mag75,int(c),b7of12)
s1g=block(red75,int(c),b7of12)
s1h=block(blu75,int(c),b7of12)
s1i=block(gry40,int(d),b7of12)
s1=stackhorizontal(s1a,s1b,s1c,s1d,s1e,s1f,s1g,s1h,s1i).pointresize(a,b7of12)

#section2
h=b1of12
s2a=block(cyn100,int(d),h)
s2b=block(choice,int(c),h)
s2c=block(wht75,int(6*c),h)
s2d=block(blu100,int(d),h)
s2=stackhorizontal(s2a,s2b,s2c,s2d)

#section3
h=b1of12
s3a=block(yel100,int(d),h)
s3b=ramp(int(7*c),h)
s3c=block(red100,int(d),h)
s3=stackhorizontal(s3a,s3b,s3c)

#section4
h=b3of12
s4a=block(gry15,int(d),h)
s4b=block(blk,int(c3of2),h)
s4c=block(wht100,int(c*2),h)
s4d=block(blk,int(c5of6),h)
s4e=block(blkm2,int(c1of3),h)
s4f=block(blk,int(c1of3),h)
s4g=block(blkp2,int(c1of3),h)
s4h=block(blk,int(c1of3),h)
s4i=block(blkp4,int(c1of3),h)
s4j=block(blk,int(c),h)
s4k=block(gry15,int(d),h)
s4=stackhorizontal(s4a,s4b,s4c,s4d,s4e,s4f,s4g,s4h,s4i,s4j,s4k).pointresize(a,h)
arib_std_b28=stackvertical(s1,s2,s3,s4)
arib_std_b28
Personal tools