diff options
Diffstat (limited to 'Master/texmf-dist/doc/asymptote/examples/tvgen.asy')
-rw-r--r-- | Master/texmf-dist/doc/asymptote/examples/tvgen.asy | 1314 |
1 files changed, 1314 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/asymptote/examples/tvgen.asy b/Master/texmf-dist/doc/asymptote/examples/tvgen.asy new file mode 100644 index 00000000000..ade90e89211 --- /dev/null +++ b/Master/texmf-dist/doc/asymptote/examples/tvgen.asy @@ -0,0 +1,1314 @@ +/* tvgen - draw pm5544-like television test cards. + * Copyright (C) 2007, 2009, Servaas Vandenberghe. + * + * The tvgen code below is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with tvgen: see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * tvgen-1.1/tvgen.asy + * This asy script generates pm5544-like television test cards. The image + * parameters were derived from a 1990 recording. The basic parameters + * conform to itu-r bt.470, bt.601, and bt.709. There is no unique image + * since local variants exist and parameters have varied over time. + */ +//papertype="a4"; +import plain; +int verbose=settings.verbose/*+2*/; /* uncomment for debug info */ + +/* tv dot coordinates --> PS points */ +pair tvps(real col, real row, real xd, real yd, int Nv) { + real psx, psy; + psx=col*xd; psy=(Nv-row)*yd; + return (psx,psy); +} +path tvrect(int lc, int tr, int rc, int br, real xd, real yd, int Nv) { + real lx, ty, rx, by; + pair[] z; + + lx=lc*xd; ty=(Nv-tr)*yd; + rx=rc*xd; by=(Nv-br)*yd; + /* bl br tr tl */ + z[0]=(lx, by); + z[1]=(rx, by); + z[2]=(rx, ty); + z[3]=(lx, ty); + + return z[0]--z[1]--z[2]--z[3]--cycle; +} + +/********************* image aspect ratio markers ********************/ +void rimarkers(real rimage, int Nh, int Nhc, int os, int Nvc, int Nsy, pen pdef, real xd, real yd, int Nv) { + int[] ridefN={ 4, 16 }; + int[] ridefD={ 3, 9 }; + int i; + + for(i=0; i<2; ++i) { + real rid=ridefN[i]/ridefD[i]; + + if(rimage>rid) { + int off, offa, offb; + + /* Nhdef=Nh/rimage*rid */ + off=round(Nh/rimage*rid/2); + offa=off+os; + offb=off-os; + // write(offa,offb); + + if(2*offa<Nh) { + int hy, tr, br; + path zz; + + hy=floor(Nsy/3); + tr=Nvc-hy; + br=Nvc+hy; + + zz=tvrect(Nhc+offb, tr, Nhc+offa, br, xd,yd,Nv); + //dot(zz); + fill(zz, p=pdef); + zz=tvrect(Nhc-offa, tr, Nhc-offb, br, xd,yd,Nv); + fill(zz, p=pdef); + } + } + } /* for i */ + return; +} + +/************* cross hatch: line pairing, center interlace test *************/ +void centerline(int[] coff, int[] coffa, int[] coffb, int Nhc, int divsx, + int os, int[] rcrowc, int Nvc, int divsy, + pair ccenter, real[] rcoff, pair[] rcright, pair[] rcleft, + pen pdef, real xd, real yd, int Nv) { + pair[] z; + int col; + pen pblack=pdef+gray(0.0), pwhite=pdef+gray(1.0); + + z[0]=rcright[divsy]; + + col=Nhc+coff[0]; + z[1]=tvps(col,rcrowc[divsy], xd,yd,Nv); + z[2]=tvps(col,rcrowc[divsy-1], xd,yd,Nv); + col=Nhc-coff[0]; + z[3]=tvps(col,rcrowc[divsy-1], xd,yd,Nv); + z[4]=tvps(col,rcrowc[divsy], xd,yd,Nv); + + z[5]=rcleft[divsy]; + z[6]=rcleft[divsy+1]; + + z[7]=tvps(col,rcrowc[divsy+1], xd,yd,Nv); + z[8]=tvps(col,rcrowc[divsy+2], xd,yd,Nv); + col=Nhc+coff[0]; + z[9]=tvps(col,rcrowc[divsy+2], xd,yd,Nv); + z[10]=tvps(col,rcrowc[divsy+1], xd,yd,Nv); + + z[11]=rcright[divsy+1]; + fill(z[1]--z[2]--z[3]--z[4] //--z[5]--z[6] + --arc(ccenter, z[5], z[6]) + --z[7]--z[8]--z[9]--z[10] //--z[11]--z[0] + --arc(ccenter,z[11], z[0]) + --cycle, p=pblack); + + int i, maxoff, rows, tr, br; + path zz; + + maxoff=floor(rcoff[divsy]); + + /* center cross: vertical and horizontal centerline */ + rows=min(Nvc-rcrowc[divsy-1], rcrowc[divsy+2]-Nvc); + tr=Nvc-rows; + br=Nvc+rows; + //write("centerline long: rows tr br ", rows, tr, br); + zz=tvrect(Nhc-os, tr, Nhc+os, br, xd,yd,Nv); + fill(zz, p=pwhite); + zz=tvrect(Nhc-maxoff,Nvc-1, Nhc+maxoff,Nvc+1, xd,yd,Nv); + fill(zz, p=pwhite); + + /* vertical short lines */ + rows=min(Nvc-rcrowc[divsy], rcrowc[divsy+1]-Nvc); + tr=Nvc-rows; + br=Nvc+rows; + if(verbose>1) + write("centerline: rows tr br ", rows, tr, br); + for(i=0; i<=divsx; ++i) { + int off; + + off=coff[i]; + if(off<maxoff) { + int offa, offb; + path zzv; + offa=coffa[i]; + offb=coffb[i]; + + zzv=tvrect(Nhc+offb, tr, Nhc+offa, br, xd,yd,Nv); + fill(zzv, p=pwhite); + zzv=tvrect(Nhc-offa, tr, Nhc-offb, br, xd,yd,Nv); + fill(zzv, p=pwhite); + } + } + return; +} + +/************************ topbw **************************************/ +void topbw(int[] coff, int Nhc, int os, int urow, int trow, int brow, + pair ccenter, pair rclt, pair rclb, pair rcrt, pair rcrb, + pen pdef, real xd, real yd, int Nv) { + pen pblack=pdef+gray(0.0), pwhite=pdef+gray(1.0); + pair[] ze; + path zext, zref, zint; + int off, col, cr; + + off=ceil((coff[2]+coff[3])/2); + ze[0]=tvps(Nhc+off,trow, xd,yd,Nv); + ze[1]=rcrt; + ze[2]=rclt; + ze[3]=tvps(Nhc-off,trow, xd,yd,Nv); + ze[4]=tvps(Nhc-off,brow, xd,yd,Nv); + col=Nhc-coff[2]-os; + ze[5]=tvps(col,brow, xd,yd,Nv); + ze[6]=tvps(col,trow, xd,yd,Nv); + cr=col+3*os; /* reflection test black pulse */ + zref=tvrect(col,trow, cr,brow, xd,yd,Nv); + ze[7]=tvps(cr,trow, xd,yd,Nv); + ze[8]=tvps(cr,brow, xd,yd,Nv); + ze[9]=tvps(Nhc+off,brow, xd,yd,Nv); + //dot(ze); + + zext=ze[0] // --ze[1]--ze[2] + --arc(ccenter, ze[1], ze[2]) + --ze[3]--ze[4]--ze[5]--ze[6]--ze[7]--ze[8]--ze[9]--cycle; + + off=ceil((coff[1]+coff[2])/2); + zint=tvrect(Nhc-off,urow, Nhc+off,trow, xd,yd,Nv); + + /* paths are completely resolved; no free endpoint conditions */ + fill(zext^^reverse(zint), p=pwhite); + fill(zint, p=pblack); + fill(zref, p=pblack); + + fill(arc(ccenter,rclt,rclb)--ze[4]--ze[3]--cycle, p=pblack); + fill(arc(ccenter,rcrb,rcrt)--ze[0]--ze[9]--cycle, p=pblack); + return; +} + +/************************ testtone **************************************/ +/* x on circle -> return y>=0 + * in: + * x x-coordinate relative to origin + * crad circle radius in y units, true size=crad*yd + */ +real testcircx(real x, real crad, real xd, real yd) { + real relx, phi, y; + + relx=x*xd/yd/crad; + if(relx>1) { + phi=0; + } else { + phi=acos(relx); + } + y=crad*sin(phi); // or (x*xd)^2+(y*yd)^2=(crad*yd)^2 + + return y; +} +/* y on circle -> return x>=0 */ +real testcircy(real y, real crad, real xd, real yd) { + real rely, phi, x; + + rely=y/crad; + if(rely>1) { + phi=pi/2; + } else { + phi=asin(rely); + } + x=crad*cos(phi)*yd/xd; // or (x*xd)^2+(y*yd)^2=(crad*yd)^2 + + return x; +} + +/* brow>trow && xb>xt */ +void testtone(real Tt, int trow, int brow, + real ccol, real crow, real crad, + pen pdef, real xd, real yd, int Nv) { + int blocks, i; + real yt, xt, yb, xb, Ttt=Tt/2; + pair ccenter; + + yt=crow-trow; + xt=testcircy(yt, crad, xd, yd); + yb=crow-brow; + xb=testcircy(yb, crad, xd, yd); + //write('#xt yt\t',xt,yt); write('#xb yb\t',xb,yb); + + ccenter=tvps(ccol,crow, xd,yd,Nv); + + blocks=floor(2*xb/Tt); + + for(i=-blocks-1; i<=blocks; ++i) { + real tl, tr; + path zz; + + tl=max(-xb,min(i*Ttt,xb)); /* limit [-xb..xb] */ + tr=max(-xb,min((i+1)*Ttt,xb)); + + if(tl<-xt && tr<=-xt || tr>xt && tl>=xt) { /* top full circle */ + pair[] z; + real yl, yr; + + yl=testcircx(tl, crad, xd, yd); + yr=testcircx(tr, crad, xd, yd); + + z[0]=tvps(ccol+tl,brow, xd,yd,Nv); + z[1]=tvps(ccol+tr,brow, xd,yd,Nv); + z[2]=tvps(ccol+tr,crow-yr, xd,yd,Nv); + z[3]=tvps(ccol+tl,crow-yl, xd,yd,Nv); + + zz=z[0]--z[1]--arc(ccenter,z[2],z[3])--cycle; + } else if(tl<-xt) { /* tl in circel, tr not, partial */ + pair[] z; + real yl; + + yl=testcircx(tl, crad, xd, yd); + + z[0]=tvps(ccol+tl,brow, xd,yd,Nv); + z[1]=tvps(ccol+tr,brow, xd,yd,Nv); + z[2]=tvps(ccol+tr,trow, xd,yd,Nv); + z[3]=tvps(ccol-xt,trow, xd,yd,Nv); + z[4]=tvps(ccol+tl,crow-yl, xd,yd,Nv); + + zz=z[0]--z[1]--z[2]--arc(ccenter,z[3],z[4])--cycle; + } else if(tr>xt) { /* tr in circle, tl not, partial */ + pair[] z; + real yr; + + yr=testcircx(tr, crad, xd, yd); + + z[0]=tvps(ccol+tl,brow, xd,yd,Nv); + z[1]=tvps(ccol+tr,brow, xd,yd,Nv); + z[2]=tvps(ccol+tr,crow-yr, xd,yd,Nv); + z[3]=tvps(ccol+xt,trow, xd,yd,Nv); + z[4]=tvps(ccol+tl,trow, xd,yd,Nv); + zz=z[0]--z[1]--arc(ccenter,z[2],z[3])--z[4]--cycle; + } else { /* full block */ + pair[] z; + + z[0]=tvps(ccol+tr,trow, xd,yd,Nv); + z[1]=tvps(ccol+tl,trow, xd,yd,Nv); + z[2]=tvps(ccol+tl,brow, xd,yd,Nv); + z[3]=tvps(ccol+tr,brow, xd,yd,Nv); + zz=z[0]--z[1]--z[2]--z[3]--cycle; + } + + if(tl<tr) { + if(i%2 == 0) { + fill(zz, p=pdef+gray(0.0)); + } else { + fill(zz, p=pdef+gray(0.75)); + } + } + } + return; +} + +/************************ color bars *************************************/ +void colorbars(int[] coff, int Nhc, int trow, int crow, int brow, + pair ccenter, pair rclt, pair rclb, pair rcrt, pair rcrb, + pen pdef, real xd, real yd, int Nv) { + real cI=0.75; + real[] cR={ cI, 0, 0, cI, cI, 0 }; + real[] cG={ cI, cI, cI, 0, 0, 0 }; + real[] cB={ 0, cI, 0, cI, 0, cI }; + int cmax=2, poff, rows, i; + + rows=brow-trow; + poff=0; + for(i=0; i<=cmax; ++i) { + int off; + int ii=2*i, il=cmax-i, ir=i+cmax+1; + path zzl, zzr; + + off=ceil((coff[1+ii]+coff[2+ii])/2); + if(i!=0 && i<cmax) { + zzr=tvrect(Nhc+poff,trow, Nhc+off,brow, xd,yd,Nv); + zzl=tvrect(Nhc-off,trow, Nhc-poff,brow, xd,yd,Nv); + } else { + if(i==0) { + int col, pcol; + pair[] zl, zr; + + col=Nhc+off; + pcol=Nhc+poff; + zr[0]=tvps(col,trow, xd,yd,Nv); + zr[1]=tvps(pcol,trow, xd,yd,Nv); + zr[2]=tvps(pcol,crow, xd,yd,Nv); + zr[3]=tvps(Nhc+coff[0],crow, xd,yd,Nv); + zr[4]=tvps(Nhc+coff[0],brow, xd,yd,Nv); + zr[5]=tvps(col,brow, xd,yd,Nv); + zzr=zr[0]--zr[1]--zr[2]--zr[3]--zr[4]--zr[5]--cycle; + + col=Nhc-off; + pcol=Nhc-poff; + zl[0]=tvps(pcol,trow, xd,yd,Nv); + zl[1]=tvps(col,trow, xd,yd,Nv); + zl[2]=tvps(col,brow, xd,yd,Nv); + zl[3]=tvps(Nhc-coff[0],brow, xd,yd,Nv); + zl[4]=tvps(Nhc-coff[0],crow, xd,yd,Nv); + zl[5]=tvps(pcol,crow, xd,yd,Nv); + zzl=zl[0]--zl[1]--zl[2]--zl[3]--zl[4]--zl[5]--cycle; + } else { + int pcol; + pair[] zl, zr; + + pcol=Nhc+poff; + zr[0]=tvps(pcol,brow, xd,yd,Nv); + zr[1]=rcrb; + zr[2]=rcrt; + zr[3]=tvps(pcol,trow, xd,yd,Nv); + zzr=zr[0]--arc(ccenter,zr[1],zr[2])--zr[3]--cycle; + + pcol=Nhc-poff; + zl[0]=tvps(pcol,trow, xd,yd,Nv); + zl[1]=rclt; + zl[2]=rclb; + zl[3]=tvps(pcol,brow, xd,yd,Nv); + zzl=zl[0]--arc(ccenter,zl[1],zl[2])--zl[3]--cycle; + } + } + fill(zzr, p=pdef+rgb(cR[ir], cG[ir], cB[ir])); + fill(zzl, p=pdef+rgb(cR[il], cG[il], cB[il])); + + poff=off; + } + return; +} + +/************************ test frequencies ****************************/ +/* in + * theta rad + * freq 1/hdot + * step hdot + * out + * new phase theta + */ +real addphase(real theta, real freq, real step) { + real cycles, thetaret; + int coverflow; + + cycles=freq*step; + coverflow=floor(abs(cycles)); + if(coverflow>1) { + thetaret=0; + } else { + real dpi=2*pi; + + cycles-=coverflow*sgn(cycles); + thetaret=theta+cycles*dpi; /* cycles=(-1 .. 1) */ + + if(thetaret>pi) { + thetaret-=dpi; + } else if(thetaret<-pi) { + thetaret-=dpi; + } + } + + //write("addphase: ", step, theta, thetaret); + return thetaret; +} + +void testfreqs(real[] ftones, int[] coff, int Nhc, int trow,int crow,int brow, + pair ccenter, pair rclt, pair rclb, pair rcrt, pair rcrb, + pen pdef, real xd, real yd, int Nv) { + int[] divc; + real[] divfl, divfr; + int i, divs, coffmax, off, divnext; + real fl, fr, thr, thl; + + /* Segment info for PAL continental test card + * segment i extends from [divc[i] .. divc[i+1]) with frequency divf[i] + */ + divs=2; // the number of segments on the right, total=2*divs+1 + divc[0]=0; + for(i=0; i<=divs; ++i) { + int ii=i*2, il=divs-i, ir=divs+i; + + divc[i+1]=ceil((coff[ii]+coff[ii+1])/2); /* xdot distance to center */ + + divfl[i]=ftones[divs-i]; + divfr[i]=ftones[divs+i]; + } + coffmax=divc[divs+1]; + + int trowlim=coff[0]; + int tr; + + tr=crow; + + divnext=0; + fl=0; + fr=0; + thl=0; + thr=0; + // draw a vertical line at off..off+1 + for(off=0; off<coffmax; ++off) { + real ampl, ampr; + int col; + path zz; + + if(off==trowlim) { + tr=trow; + } + + if(off == divc[divnext]) { + /* switch frequency: cycles=0.5*fcur+0.5*fnext */ + thl=addphase(thl, fl, -0.5); + thr=addphase(thr, fr, 0.5); + fl=divfl[divnext]; + fr=divfr[divnext]; + thl=addphase(thl, fl, -0.5); + thr=addphase(thr, fr, 0.5); + + ++divnext; + // thl=pi; thr=pi; + //write(off, fl, fr); + } else { + thl=addphase(thl, fl, -1); + thr=addphase(thr, fr, 1); + // thl=0; thr=0; + } + + ampl=(1+sin(thl))/2; + ampr=(1+sin(thr))/2; + //write(off, thr, ampr); + + col=Nhc-off-1; + zz=tvrect(col,tr, col+1,brow, xd,yd,Nv); + fill(zz, p=pdef+gray(ampl)); + col=Nhc+off; + zz=tvrect(col,tr, col+1,brow, xd,yd,Nv); + fill(zz, p=pdef+gray(ampr)); + } + + pair[] z; + z[0]=tvps(Nhc-coffmax,trow, xd,yd,Nv); + z[1]=tvps(Nhc-coffmax,brow, xd,yd,Nv); + fill(z[0]--arc(ccenter,rclt,rclb)--z[1]--cycle, p=pdef+gray(0.0)); + z[0]=tvps(Nhc+coffmax,brow, xd,yd,Nv); + z[1]=tvps(Nhc+coffmax,trow, xd,yd,Nv); + fill(z[0]--arc(ccenter,rcrb,rcrt)--z[1]--cycle, p=pdef+gray(0.0)); + return; +} + +/************************ gray bars **************************************/ +void graybars(int[] coff, int Nhc, int trow, int brow, + pair ccenter, pair rclt, pair rclb, pair rcrt, pair rcrb, + pen pdef, real xd, real yd, int Nv) { + int[] gs={0, 51, 102, 153, 204, 255}; + int cmax=2, poff, rows, i; + + rows=brow-trow; + poff=0; + for(i=0; i<=cmax; ++i) { + int off; + int ii=2*i, il=cmax-i, ir=i+cmax+1; + path zzl, zzr; + + off=ceil((coff[1+ii]+coff[2+ii])/2); + if(i<cmax) { + zzl=tvrect(Nhc-off,trow, Nhc-poff,brow, xd,yd,Nv); + zzr=tvrect(Nhc+poff,trow, Nhc+off,brow, xd,yd,Nv); + } else { + int pcol; + pair zlt, zlb, zrt, zrb; + + pcol=Nhc-poff; + zlt=tvps(pcol,trow, xd,yd,Nv); + zlb=tvps(pcol,brow, xd,yd,Nv); + zzl=zlt--arc(ccenter,rclt,rclb)--zlb--cycle; + + pcol=Nhc+poff; + zrb=tvps(pcol,brow, xd,yd,Nv); + zrt=tvps(pcol,trow, xd,yd,Nv); + zzr=zrb--arc(ccenter,rcrb,rcrt)--zrt--cycle; + } + fill(zzl, p=pdef+gray(gs[il]/255)); + fill(zzr, p=pdef+gray(gs[ir]/255)); + + poff=off; + } + return; +} + +/************************ bottom bw **************************************/ +void bottombw(int off, int Nhc, int trow, int brow, + pair ccenter, pair rclt, pair rclb, pair rcrt, pair rcrb, + pen pdef, real xd, real yd, int Nv) { + int rows; + pair zt, zb; + path zz; + + rows=brow-trow; + zz=tvrect(Nhc-off,trow, Nhc+off,brow, xd,yd,Nv); + fill(zz, p=pdef+gray(0.0)); + + zt=tvps(Nhc-off,trow, xd,yd,Nv); + zb=tvps(Nhc-off,brow, xd,yd,Nv); + fill(zt--arc(ccenter,rclt,rclb)--zb--cycle, p=pdef+gray(1.0)); + + zb=tvps(Nhc+off,brow, xd,yd,Nv); + zt=tvps(Nhc+off,trow, xd,yd,Nv); + fill(zb--arc(ccenter,rcrb,rcrt)--zt--cycle, p=pdef+gray(1.0)); + return; +} + +/************************ bottom circle **************************************/ +void bottomcirc(int off, int Nhc, int trow, real cx, real cy, real crad, + pair ccenter, pair rclt, pair rcrt, + pen pdef, real xd, real yd, int Nv) { + real cI=0.75; + real xl, yl, xr, yr, phil, phir; + pair ccleft, ccright; + pair[] z; + + xl=Nhc-off-cx; + phil=acos(xl*xd/yd/crad); + yl=crad*sin(phil); // or (x*xd)^2+(y*yd)^2=(crad*yd)^2 + ccleft=tvps(cx+xl,cy+yl, xd,yd,Nv); + //write(xl,yl); + + xr=Nhc+off-cx; + phir=acos(xr*xd/yd/crad); + yr=crad*sin(phir); + ccright=tvps(cx+xr,cy+yr, xd,yd,Nv); + + //dot(ccright); dot(ccleft); + // red center + z[0]=tvps(Nhc-off,trow, xd,yd,Nv); + z[1]=ccleft; + z[2]=ccright; + z[3]=tvps(Nhc+off,trow, xd,yd,Nv); + fill(z[0]--arc(ccenter,z[1],z[2])--z[3]--cycle, p=pdef+rgb(cI,0,0)); + + // yellow + z[0]=tvps(Nhc-off,trow, xd,yd,Nv); + z[1]=rclt; + z[2]=ccleft; + fill(z[0]--arc(ccenter,z[1],z[2])--cycle, p=pdef+rgb(cI,cI,0)); + z[0]=tvps(Nhc+off,trow, xd,yd,Nv); + z[1]=ccright; + z[2]=rcrt; + fill(z[0]--arc(ccenter,z[1],z[2])--cycle, p=pdef+rgb(cI,cI,0)); + + return; +} + +/****************************** PAL ears *********************************** + * left y R G B + * 0.55 98 162 140 + * 0.5 103 128 191 + * 0.5 152 128 64 + * 0.45 157 93 115 + * right + * 0.6 153 168 76 + * 0.4 102 87 179 + * + * in: dright= -1 left ear, +1 right ear + */ +void palears(int[] coff, int[] coffa, int[] coffb, int Nhc, + int[] rcrowt, int[] rcrowb, int Nvc, int divsy, int dright, + pen pdef, real xd, real yd, int Nv) { + /* the amplitude of (u,v) as seen on a vectorscope, + * max 0.296 Vn for 100% saturation in W and V ears. + * cvbs: 0.7*( y +/- |u+jv| ) = -0.24 .. 0.93 V + * maxima: ebu 75/0 bars 0.70, bbc 100/25 0.88, 100/0 bars 0.93 + * burst: 0.150 Vcvbs, 21.4 IRE or 0.214 V normalized. + * luma: modulated for monochrome compatibility, 1990 version. + * choice: set amplitude of subcarrier equal to amplitude of colorburst. + */ + real cI=0.214; + + /* (u,v) for zero G-y, phase of -34.5 degrees */ + real wr=0.299, wb=0.114, wg=1-wr-wb; /* wg=0.587, y=wr*R+wg*G+wb*B */ + real wu=0.493, wv=0.877; /* u=wu*(B-y) v=wv*(R-y) */ + real colu=wu*wg/wb, colv=-wv*wg/wr; /* for w=(G-y)/0.696 == 0 */ + + /* ears: U==0 W==0 W==0 U==0 */ + real[] cyl={ 0.55, 0.5, 0.5, 0.45 }; + real[] cul={ 0, colu, -colu, 0 }; + real[] cvl={ -1, colv, -colv, 1 }; + + /* ears: V==0 W==0 W==0 V==0 */ + real[] cyr={ 0.60, 0.5, 0.5, 0.40 }; + real[] cur={ -1, colu, -colu, 1 }; + real[] cvr={ 0, colv, -colv, 0 }; + + real[] cy, cu, cv; + pair[] z; + path[] zz; + int lcol, ccol, cicol, rcol, i; + + if(dright>0) { + cy=cyr; cu=cur; cv=cvr; + } else { + cy=cyl; cu=cul; cv=cvl; + } + + lcol=Nhc+dright*coffa[5]; + ccol=Nhc+dright*coff[6]; + cicol=Nhc+dright*coffa[6]; + rcol=Nhc+dright*coffb[7]; + + int urow, trow, crow, brow, arow; + urow=rcrowb[divsy-5]; + trow=rcrowt[divsy-3]; + crow=Nvc; + brow=rcrowb[divsy+4]; + arow=rcrowt[divsy+6]; + + z[0]=tvps(ccol,urow, xd,yd,Nv); + z[1]=tvps(ccol,trow, xd,yd,Nv); + z[2]=tvps(cicol,trow, xd,yd,Nv); + z[3]=tvps(cicol,crow, xd,yd,Nv); + z[4]=tvps(rcol,crow, xd,yd,Nv); + z[5]=tvps(rcol,urow, xd,yd,Nv); + zz[0]=z[0]--z[1]--z[2]--z[3]--z[4]--z[5]--cycle; + + zz[1]=tvrect(lcol,urow, ccol,trow, xd,yd,Nv); + zz[2]=tvrect(lcol,brow, ccol,arow, xd,yd,Nv); + + z[0]=tvps(ccol,arow, xd,yd,Nv); + z[1]=tvps(ccol,brow, xd,yd,Nv); + z[2]=tvps(cicol,brow, xd,yd,Nv); + z[3]=tvps(cicol,crow, xd,yd,Nv); + z[4]=tvps(rcol,crow, xd,yd,Nv); + z[5]=tvps(rcol,arow, xd,yd,Nv); + zz[3]=z[0]--z[1]--z[2]--z[3]--z[4]--z[5]--cycle; + + for(i=0; i<4; ++i) { + real y, u, v, A, ph, By, Ry, Gy, R, G, B; + + y=cy[i]; + u=cu[i]; + v=cv[i]; + + A=hypot(u,v); + ph= (u!=0 || v!=0) ? atan2(v,u) : 0.0; + if(v>=0) { + if(ph<0) ph=ph+pi; + } else { + if(ph>0) ph=ph-pi; + } + if(A>0) { + u=u/A*cI; + v=v/A*cI; + } + + By=u/wu; + Ry=v/wv; + Gy=(-wr*Ry-wb*By)/wg; + //write(y,Gy,A,ph*180/pi); + + R=Ry+y; + G=Gy+y; + B=By+y; + if(verbose > 1) + write(y,round(R*255),round(G*255),round(B*255)); + + fill(zz[i], p=pdef+rgb(R,G,B)); + } + return; +} + +/****************************** NTSC bars *********************************** + * amplitude equals color burst smpte (pm: -V +U) + * y campl sat R G B + * left 0.5 0.21 70% -I? + * right 0.5 0.17 60% +Q? + */ +void ntscbars(int[] coff, int[] coffa, int[] coffb, int Nhc, + int[] rcrowt, int[] rcrowb, int Nvc, int divsy, int dright, + pen pdef, real xd, real yd, int Nv) { + /* The amplitude of (i,q) as seen on a vectorscope, + * max 0.292 Vn for 100% saturation in I==0 ears. + * burst: 0.143 Vcvbs, 20 IRE or 0.200 V normalized. + * pedestal: (yp,up,vp)=(p,0,0)+(1-p)*(y,u,v), p=0.075. + * choice: equal amplitude for colorburst and subcarrier. + */ + real campl=0.200/0.925; + + /* wg=0.587, y=wr*R+wg*G+wb*B */ + real wr=0.299, wb=0.114, wg=1-wr-wb; + /* iT : iq -> RyBy : rotation+scaling */ + real iT11=0.95, iT12=0.62, iT21=-1.11, iT22=1.71; + + /* bars -2 -1 0 1 2 */ + real[] cyl={ 0.50, 0.50, 0, 0.50, 0.50 }; + real[] cil={ 0, 0, 0, -1, 1 }; + real[] cql={ -1, 1, 0, 0, 0 }; + int[] offil={ 6, 7, 5, 7, 6 }; + + real cy, ci, cq; + int dri, dris, offi, lcol, rcol, i; + + if(dright>=0) { + dris=1; + } else { + dris=-1; + } + if(dright<-2 || dright>2) { + dri=2; + } else { + dri=2+dright; + } + + cy=cyl[dri]; ci=cil[dri]; cq=cql[dri]; + offi=offil[dri]; + lcol=Nhc+dris*coffa[offi]; + rcol=Nhc+dris*coffb[offi+1]; + + real A, By, Ry, Gy, R, G, B; + + A=hypot(ci,cq); + if(A>0) { + ci=ci/A*campl; + cq=cq/A*campl; + } + Ry=iT11*ci+iT12*cq; + By=iT21*ci+iT22*cq; + Gy=(-wr*Ry-wb*By)/wg; + //write(cy,Ry,Gy,By); + + R=Ry+cy; + G=Gy+cy; + B=By+cy; + if(verbose > 1) + write(cy,ci,cq,round(R*255),round(G*255),round(B*255)); + + for(i=-divsy; i<=divsy; ++i) { + path zz; + int brow, trow; + + if(i>-divsy) { + trow=rcrowb[divsy+i]; + } else { + trow=floor((rcrowb[divsy+i]+rcrowt[divsy+i+1])/2); + } + + if(divsy>i) { + brow=rcrowt[divsy+i+1]; + } else { + brow=floor((rcrowb[divsy+i]+rcrowt[divsy+i+1])/2); + } + + zz=tvrect(lcol,brow, rcol,trow, xd,yd,Nv); + fill(zz, p=pdef+rgb(R,G,B)); + } + + return; +} + + +/****************************** main ***********************************/ +/* Conversion to bitmap: + * EPSPNG='gs -dQUIET -dNOPAUSE -dBATCH -sDEVICE=png16m' + * asy -u bsys=2 -u colortv=1 -u os=1 -a Z tvgen + * $EPSPNG -r132x144 -g720x576 -sOutputFile=tvgen.png tvgen.eps + * + * asy -u bsys=2 -u colortv=1 -u os=1 tvgen + */ +int bsys=2, colortv=1, os=1; + +/* bsys: broadcast system + * bsys im aspect Nh + * 0 4/3 704 guaranteed analog broadcast itu-r bt.470 + * 1 4/3 720 new broadcast, most TV station logos and animations + * 2 15/11 720 total aperture analog 4/3, 1.37 film DVDs + * 3 20/11 720 total aperture analog 16/9, 1.85 film DVDs + * 4 4/3 768 bsys=0, square dot analog broadcast + * 5 4/3 768 bsys=1, square dot cable TV info channel + * 6 131/96 786 bsys=2, total square dot broadcast camera + * 7 16/9 720 new broadcast 16/9, SD from HD-1440 or itu-r bt.709 + * 8 4/3 704 525 analog broadcast itu-r bt.470 711*485 + * 9 4/3 720 525 new broadcast + * 10 15/11 720 525 total aperture analog broadcast + * 11 16/9 1920 1250, 1080 square dot at 12.5 frames/second + * 12 4/3 1600 1250, 1200 square dot at 12.5 frames/second + * + * colortv: + * set 0 for monochrome crosshatch, 1 for pal ears, 2 for ntsc bars + * + * os: horizontal oversampling, typical values for 13.5MHz: + * 2 4/3 704*576, 15/11 720*576 + * 4 4/3 720*480 + * 5 4/3 704*480, 15/11 720*480, 4/3 768*576 14.4MHz + * 8 4/3 720*576, 20/11 720*576 + * 12 704->768 rerastering + * 16 720->768 rerastering + */ +access settings; +usersetting(); + +if(bsys<0 || bsys>12 || colortv<0 || colortv>3 || os<=0 || os>16) { + write('Error: bad user input: bsys, colortv, os=\t', bsys, colortv, os); + abort('Bad option -u bsys=N ?'); +} + +int[] bNdot= + { 12, 16, 12, 16, 1, 1, 1, 64, 10, 8, 10, 1, 1 }; +int[] bDdot= + { 11, 15, 11, 11, 1, 1, 1, 45, 11, 9, 11, 1, 1 }; +int[] bNh= + { 704, 720, 720, 720, 768, 768, 786, 720, 704, 720, 720, 1920, 1600 }; +int[] bNv= + { 576, 576, 576, 576, 576, 576, 576, 576, 480, 480, 480, 1080, 1200 }; +real[] bfs= + { 13.5,13.5,13.5,13.5, 14.75,14.4,14.75,13.5, 13.5,13.5,13.5, 36, 30 }; +int[] bNsy= + { 42, 42, 42, 42, 42, 42, 42, 42, 34, 34, 34, 78, 90 }; +int[] bNsh= + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* active lines for a 625 line frame + * The number of active video lines decreased around 1997. + * old: 3 run in + 575 visible + 3 run out = 581 lines + * new: 6 teletext and WSS + 575 visible + * Hence the image center shifted down by 3 lines. Thus + * old TV + new testcard = bottom is cut off, + * new TV + old testcard = top is cut off. + * + * To generate the old testcard either use Nv=582 Nsh=0 or Nv=576 Nsh=3. + * + * aspect ratio + * rimage=xsize/ysize rimage=rdot*Nh/Nv + * Nh=704 dots + * Nv=576 lines + * rd=ri*Nv/Nh=4/3*9/11=12/11 + * + * Nv: 480=2^5*3*5 576=2^6*3^2 + * Nh: 704=2^6*11 720=2^4*3^2*5 + * + * horizontal line distance for pre 1997 test pattern + * top 8 lines, 13 squares of Ny=43 lines, bottom 9 lines + * top 12 lines, 13 squares of Ny=42 lines, bottom 18 lines + * pairs are from odd even field + * Interlace test: Ny must be odd for a cross-hatch without centerline. + * + * squares: ly=Nsy, lx=rd*Nsx, lx=ly ==> Nsx=Nsy/rd={ 39.4, 38.5 } + * x line width 230 ns -> 3 dots + * bottom 2.9us red -> 39.15 dots + * + * resolution DPI from image aspect ratio + * Rv=Nv/ly, ly=4in + * ri=Ni/Di, Ni={4,15,16} Di={3,11,9} + * lx=ri*ly + * + * Rh=Nh/lx=Di*(Nh/(Ni*ly)) + * ==> ri=4/Di => Nh=k*16 + * ri=15/Di => Nh=k*60 + * ri=16/Di => Nh=k*64 + * + * resolution DPI from dot aspect ratio, general algorithm, + * + * rd=Nd/Dd=ldx/ldy + * + * assume 1 dot = Nd x Dd square subdots at a resolution of k, in dpi, then + * + * ldx=Nd/k, ldy=Dd/k ==> Rh=k/Nd, Rv=k/Dd + * + * choosing k=m*Nd*Dd for integer Rh and Rv gives + * + * ldx=1/(m*Dd), ldy=1/(m*Nd), Rh=m*Dd, Rv=m*Nd + * + * and + * + * lx=Nh*ldx=Nh/(m*Dd), ly=Nv*ldy=Nv/(m*Nd) + * + * so choose m for the intended height Ly, in inch, as + * + * m=round(Nv/(Ly*Nd)) + * + * which limits Ly<=Nv/Nd since Rv>=Nd. + */ +//cm=72/2.540005; +real Ly, ly, lx, ysize, xsize, rimage, xd, yd, pwidth; +int Nd, Dd, m, Nh, Nv, Nshift, Na, Nsy; +real fs, Ttone; + +Nd=bNdot[bsys]; +Dd=bDdot[bsys]*os; +Nh=bNh[bsys]*os; +Nv=bNv[bsys]; + +Ly=4; // 4 inch vertical size +m=floor(0.5+Nv/(Ly*Nd)); +if(m<1) m=1; +ly=Nv/(m*Nd); +lx=Nh/(m*Dd); + +ysize=ly*1inch; +xsize=lx*1inch; +rimage=xsize/ysize; +if(verbose > 1) + write('#Nd Dd m ri:\t', Nd, Dd, m, rimage); +//size(xsize,ysize,Aspect); // should not have any effect + +Nsy=bNsy[bsys]; // grating size in lines 42,43, 34,35 +Nshift=bNsh[bsys]; // shift image up: pre 1997 =3, 2007 =0 +fs=1e6*bfs[bsys]*os; +Na=0; // add 1,0,-1 to height of hor center squares for even Na+Nsy + +Ttone=fs/250e3; // period of ft=250 kHz, fs/ft=54 +real[] ftones={0.8e6/fs, 1.8e6/fs, 2.8e6/fs, 3.8e6/fs, 4.8e6/fs}; + +xd=xsize/Nh; +yd=ysize/Nv; +pwidth=min(abs(xd),abs(yd)); + +pen pdefault=squarecap+linewidth(pwidth); +pen pblack=pdefault+gray(0.0); +pen pwhite=pdefault+gray(1.0); + +/**** calculate grating repeats and size in tv dots ****/ +// horizontal lines +int divsy, rdisty, Nvc, Nt, Nb; + +Nvc=floor(Nv/2)-Nshift; +divsy=floor(((Nv-Na-2)/Nsy-1)/2); // (Nv-Na-2)/2-Nsy/2 dots for Nsy lengths +rdisty=Na+Nsy*(1+2*divsy); +Nt=Nvc-ceil(rdisty/2); +Nb=Nv-Nt-rdisty; +if(verbose > 1) + write('#divsy t b: \t',divsy,Nt,Nb); + +/* Nsyc: center square height + * line pairing test: verify distance of center to top and bot + * distance is odd ==> top=even/odd, cent=odd/even, bot=even/odd + * + * Nsyc odd: not possible + * + * Nsyc even: + * Nsyc/2 odd --> OK + * Nsyc/2 even --> stagger the raster one line upwards + * + * rcrowt top dist of hor line + * rcrowc true center for color info, distance to top of image. + * rcrowb bot dist of hor line + * + * Nt=Nvc-(offu+divsy*Nsy); + * Nb=Nv-( Nvc-(offd-divsy*Nsy) ); + * ==> Nt+Nb=Nv-Nsyc-2*divsy*Nsy + */ +int Nsyc, offu, offd, Nyst=0, i; +int[] rcrowt, rcrowc, rcrowb; + +Nsyc=Nsy+Na; +offu=floor(Nsyc/2); +offd=offu-Nsyc; +if(Nsyc%2 != 0) { + Nyst=1; +} else if(Nsyc%4 == 0) { + Nyst=1; /* stagger */ +} +for(i=0; i<=divsy; ++i) { + int iu, id, ou, od, ru, rd; + + iu=divsy-i; + id=divsy+i+1; + + ou=offu+Nsy*i; + od=offd-Nsy*i; + if(verbose > 1) + write(ou,od); + rcrowc[iu]=Nvc-ou; + rcrowc[id]=Nvc-od; + + ru=Nvc-(ou+Nyst); + rd=Nvc-(od+Nyst); + + rcrowt[iu]=ru-1; + rcrowb[iu]=ru+1; + + rcrowt[id]=rd-1; + rcrowb[id]=rd+1; +} +Nt=floor((rcrowt[0]+rcrowb[0])/2); +Nb=Nv-Nt-Nsyc-2*Nsy*divsy; +if(verbose > 1) + write('#st t b: \t',Nyst,Nt,Nb); + +/* vertical lines + * (Nh-2*os)/2-Nsx/2 dots available for divisions of Nsx dots. + * At least 5 dots margin left and right ==> use -10*os + */ +real lsq, Nsx; +int divsx, Nhc, Nl; + +lsq=Nsy*yd; +Nsx=lsq/xd; +divsx=floor(((Nh-10*os)/Nsx-1)/2); +Nhc=round(Nh/2); +Nl=Nhc-round((1+2*divsx)*Nsx/2); +if(verbose > 1) + write('#Nsx divsx Nl:\t',Nsx,divsx,Nl); + +/**** draw gray background ****/ +{ + path zz; + //zz=tvrect(0,0, Nh,Nv, xd,yd,Nv); + /* keep white canvas for castellations */ + zz=tvrect(Nl,Nt, Nh-Nl,Nv-Nb, xd,yd,Nv); + fill(zz, p=pdefault+gray(0.5)); + //dot(zz); +} +/**** draw center circle ****/ +real cx, cy, crad; +pair ccenter; +path ccirc; +cx=Nh/2; +cy=Nv/2-Nshift; +crad=6*Nsy; +if(Nv%2 != 0) { + crad+=0.5; +} +ccenter=tvps(cx,cy, xd,yd,Nv); +ccirc=circle(ccenter, crad*yd); +if(colortv<=0) { + draw(ccirc, p=pwhite+linewidth(2*yd)); +} + +/****** draw 2*divsy+2 horizontal lines **********************************/ +real[] rcang, rcoff; +pair[] rcright, rcleft; +int i, iend=2*divsy+1; +for(i=0; i<=iend; ++i) { + real y, phi, x; + path zzh; + pair zd; + + zzh=tvrect(0,rcrowt[i], Nh,rcrowb[i], xd,yd,Nv); + fill(zzh, p=pwhite); + + y=cy-rcrowc[i]; + //write(roff); + if(abs(y)<crad) { + phi=asin(y/crad); + } else { + phi=pi/2; + } + rcang[i]=phi; + x=(crad*cos(phi))*yd/xd; + rcoff[i]=x; + zd=tvps(cx+x,cy-y, xd,yd,Nv); + rcright[i]=zd; + //dot(zd); + zd=tvps(cx-x,cy-y, xd,yd,Nv); + rcleft[i]=zd; +} + +/****** draw 2*divsx+2 vertical lines ***************************/ +int[] coff, coffa, coffb; +int poffa=0, ccenterwhite=divsx%2; +for(i=0; i<=divsx; ++i) { + real cdist=(1+2*i)*Nsx; + int off, offa, offb; + path zzv; + + off=round(cdist/2); + //write(cdist,off); + offa=off+os; + offb=off-os; + + coff[i]=off; + coffa[i]=offa; + coffb[i]=offb; + + //write(Nhc-offa); + zzv=tvrect(Nhc+offb,0, Nhc+offa,Nv, xd,yd,Nv); + fill(zzv, p=pwhite); + zzv=tvrect(Nhc-offa,0, Nhc-offb,Nv, xd,yd,Nv); + fill(zzv, p=pwhite); + + /** top castellations, must end with black **/ + if(i%2 == ccenterwhite) { + int j, jnum; + + if(poffa == 0) { + poffa=-offb; + jnum=1; + } else { + jnum=2; + } + + for(j=0; j<jnum; ++j) { + int lc, rc; + path zzc; + + if(j==0) { + lc=Nhc+poffa; + rc=Nhc+offb; + } else { + lc=Nhc-offb; + rc=Nhc-poffa; + } + + zzc=tvrect(lc,0, rc,Nt-1, xd,yd,Nv); + fill(zzc, p=pblack); + zzc=tvrect(lc,Nv-Nb+1, rc,Nv, xd,yd,Nv); + fill(zzc, p=pblack); + } + } + + poffa=offa; +} +//write(coff); + +/** left and right castellations **/ +/* The bottom right red rectangle tests for a non causal color FIR + * filter in the receiver. The last 2..4 dots then typically appear + * colorless, green, or cyan. + * + * This comes from the fact that the chroma subcarrier is of lower + * bandwidth than luma and thus continues after the last active sample. + * These trailing (y,u,v) samples result from a signal to zero + * transition and depend on the transmit and receive filters. Samples + * from VHS, system B/G/D/K, system I, or a DVD player output are + * different. Nevertheless, a sharpening filter uses this data and so + * adds false color to the last dots. + */ +int lc, rc; +iend=2*divsy+1; +lc=Nhc-coffa[divsx]; +rc=Nhc+coffa[divsx]; +for(i=1; i<=iend; ++i) { + pen pcast; + if(i == iend && colortv>0) { + pcast=pdefault+rgb(0.75,0.0,0); + } else { + pcast=pblack; + } + if(i%2 == 1) { + int tr, br; + path zzc; + + tr=rcrowb[i-1]; + br=rcrowt[i]; + zzc=tvrect( 0,tr, lc,br, xd,yd,Nv); + fill(zzc, p=pblack); + zzc=tvrect(rc,tr, Nh,br, xd,yd,Nv); + fill(zzc, p=pcast); + } +} + +/****** markers for 4/3 aspect ratio ******/ +if(rimage>4/3) + rimarkers(rimage, Nh, Nhc, os, Nvc, Nsy, pwhite, xd, yd, Nv); + +/****** line pairing center ******/ +centerline(coff, coffa, coffb, Nhc, divsx, os, rcrowc, Nvc, divsy, + ccenter, rcoff, rcright, rcleft, pdefault, xd, yd, Nv); + +if(colortv>0) { + /* topbw structure */ + topbw(coff, Nhc, os, rcrowc[divsy-5], rcrowc[divsy-4], rcrowc[divsy-3], + ccenter, rcleft[divsy-4], rcleft[divsy-3], rcright[divsy-4], + rcright[divsy-3], pdefault, xd, yd, Nv); + + /* 250 kHz */ + testtone(Ttone, rcrowc[divsy-3], rcrowc[divsy-2], + cx, cy, crad, pdefault, xd, yd, Nv); + + /* color bars */ + colorbars(coff, Nhc, rcrowc[divsy-2], rcrowc[divsy-1], rcrowc[divsy], + ccenter, rcleft[divsy-2], rcleft[divsy], rcright[divsy-2], + rcright[divsy], pdefault, xd, yd, Nv); + + /* test frequencies */ + testfreqs(ftones, coff, Nhc, rcrowc[divsy+1], rcrowc[divsy+2], + rcrowc[divsy+3], ccenter, rcleft[divsy+1], rcleft[divsy+3], + rcright[divsy+1],rcright[divsy+3], pdefault, xd, yd, Nv); + + /* gray bars */ + graybars(coff, Nhc, rcrowc[divsy+3], rcrowc[divsy+4], ccenter, + rcleft[divsy+3], rcleft[divsy+4], + rcright[divsy+3], rcright[divsy+4], pdefault, xd,yd,Nv); + + /* PAL ears */ + if(colortv==1) { + palears(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, -1, + pdefault, xd, yd, Nv); + palears(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, 1, + pdefault, xd, yd, Nv); + } else if(colortv==2) { + ntscbars(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, -1, + pdefault, xd, yd, Nv); + ntscbars(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, 1, + pdefault, xd, yd, Nv); + ntscbars(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, -2, + pdefault, xd, yd, Nv); + ntscbars(coff,coffa,coffb, Nhc, rcrowt, rcrowb, Nvc, divsy, 2, + pdefault, xd, yd, Nv); + } + + /* bottom wh - black - wh */ + bottombw(round((coff[2]+coff[3])/2), Nhc, rcrowc[divsy+4], rcrowc[divsy+5], + ccenter, rcleft[divsy+4], rcleft[divsy+5], + rcright[divsy+4], rcright[divsy+5], pdefault, xd, yd, Nv); + + /* bottom yellow red circle */ + bottomcirc(coff[0], Nhc, rcrowc[divsy+5], cx, cy, crad, + ccenter, rcleft[divsy+5], rcright[divsy+5], pdefault, xd, yd, Nv); +} + +/********************** set id *********************/ +{ /* dpi */ + pair rpos=tvps(Nhc,round((rcrowc[divsy-4]+rcrowc[divsy-5])/2), xd,yd,Nv); + string iRhor, iRver, ires; + real Rh, Rv; + + Rh=Nh/xsize*inch; + Rv=Nv/ysize*inch; + iRhor=format("%.4gx", Rh); + iRver=format("%.4gdpi", Rv); + ires=insert(iRver,0, iRhor); + + /* size info */ + int rowbot=round((rcrowc[divsy+4]+rcrowc[divsy+5])/2); + pair tpos=tvps(Nhc,rowbot, xd,yd,Nv); + string ihor, iver, itot, iasp, ifm; + real asp, fm; + + ihor=format("%ix",Nh); + iver=format("%i ",Nv); + itot=insert(iver,0, ihor); + asp=xsize/ysize; + iasp=format("%.3g ",asp); + fm=fs/1e6; + ifm=format("%.4gMHz",fm); + itot=insert(iasp,0, itot); + itot=insert(ifm,0, itot); + + /* size of square */ + int rowNsy=round((rcrowc[divsy+5]+rcrowc[divsy+6])/2); + pair Npos=tvps(Nhc+round((coff[4]+coff[5])/2),rowNsy, xd,yd,Nv); + string iNsy=format("%i",Nsy); + + pen pbw; + if(colortv>0) { + pbw=pdefault+gray(1.0); + } else { + pbw=pdefault+gray(0.0); + } + label(ires, rpos, p=pbw); + label(itot, tpos, p=pbw); + label(iNsy, Npos, p=pbw); + if(verbose > 1) + write('#res:\t', ires, itot, iNsy); +} + |