📄 drawtest.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h>#include <memdraw.h>#define DBG if(0)#define RGB2K(r,g,b) ((299*((ulong)(r))+587*((ulong)(g))+114*((ulong)(b)))/1000)/* * This program tests the 'memimagedraw' primitive stochastically. * It tests the combination aspects of it thoroughly, but since the * three images it uses are disjoint, it makes no check of the * correct behavior when images overlap. That is, however, much * easier to get right and to test. */void drawonepixel(Memimage*, Point, Memimage*, Point, Memimage*, Point);void verifyone(void);void verifyline(void);void verifyrect(void);void verifyrectrepl(int, int);void putpixel(Memimage *img, Point pt, ulong nv);ulong rgbatopix(uchar, uchar, uchar, uchar);char *dchan, *schan, *mchan;int dbpp, sbpp, mbpp;int drawdebug=0;int seed;int niters = 100;int dbpp; /* bits per pixel in destination */int sbpp; /* bits per pixel in src */int mbpp; /* bits per pixel in mask */int dpm; /* pixel mask at high part of byte, in destination */int nbytes; /* in destination */int Xrange = 64;int Yrange = 8;Memimage *dst;Memimage *src;Memimage *mask;Memimage *stmp;Memimage *mtmp;Memimage *ones;uchar *dstbits;uchar *srcbits;uchar *maskbits;ulong *savedstbits;voidrdb(void){}intiprint(char *fmt, ...){ int n; va_list va; char buf[1024]; va_start(va, fmt); n = doprint(buf, buf+sizeof buf, fmt, va) - buf; va_end(va); write(1,buf,n); return 1;}voidmain(int argc, char *argv[]){ memimageinit(); seed = time(0); ARGBEGIN{ case 'x': Xrange = atoi(ARGF()); break; case 'y': Yrange = atoi(ARGF()); break; case 'n': niters = atoi(ARGF()); break; case 's': seed = atoi(ARGF()); break; }ARGEND dchan = "r8g8b8"; schan = "r8g8b8"; mchan = "r8g8b8"; switch(argc){ case 3: mchan = argv[2]; case 2: schan = argv[1]; case 1: dchan = argv[0]; case 0: break; default: goto Usage; Usage: fprint(2, "usage: dtest [dchan [schan [mchan]]]\n"); exits("usage"); } fmtinstall('b', numbconv); /* binary! */ fprint(2, "%s -x %d -y %d -s 0x%x %s %s %s\n", argv0, Xrange, Yrange, seed, dchan, schan, mchan); srand(seed); dst = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(dchan)); src = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan)); mask = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan)); stmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(schan)); mtmp = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan)); ones = allocmemimage(Rect(0, 0, Xrange, Yrange), strtochan(mchan));// print("chan %lux %lux %lux %lux %lux %lux\n", dst->chan, src->chan, mask->chan, stmp->chan, mtmp->chan, ones->chan); if(dst==0 || src==0 || mask==0 || mtmp==0 || ones==0) { Alloc: fprint(2, "dtest: allocation failed: %r\n"); exits("alloc"); } nbytes = (4*Xrange+4)*Yrange; srcbits = malloc(nbytes); dstbits = malloc(nbytes); maskbits = malloc(nbytes); savedstbits = malloc(nbytes); if(dstbits==0 || srcbits==0 || maskbits==0 || savedstbits==0) goto Alloc; dbpp = dst->depth; sbpp = src->depth; mbpp = mask->depth; dpm = 0xFF ^ (0xFF>>dbpp); memset(ones->data->bdata, 0xFF, ones->width*sizeof(ulong)*Yrange); fprint(2, "dtest: verify single pixel operation\n"); verifyone(); fprint(2, "dtest: verify full line non-replicated\n"); verifyline(); fprint(2, "dtest: verify full rectangle non-replicated\n"); verifyrect(); fprint(2, "dtest: verify full rectangle source replicated\n"); verifyrectrepl(1, 0); fprint(2, "dtest: verify full rectangle mask replicated\n"); verifyrectrepl(0, 1); fprint(2, "dtest: verify full rectangle source and mask replicated\n"); verifyrectrepl(1, 1); exits(0);}/* * Dump out an ASCII representation of an image. The label specifies * a list of characters to put at various points in the picture. */static voidBprintr5g6b5(Biobuf *bio, char*, ulong v){ int r,g,b; r = (v>>11)&31; g = (v>>5)&63; b = v&31; Bprint(bio, "%.2x%.2x%.2x", r,g,b);}static voidBprintr5g5b5a1(Biobuf *bio, char*, ulong v){ int r,g,b,a; r = (v>>11)&31; g = (v>>6)&31; b = (v>>1)&31; a = v&1; Bprint(bio, "%.2x%.2x%.2x%.2x", r,g,b,a);}voiddumpimage(char *name, Memimage *img, void *vdata, Point labelpt){ Biobuf b; uchar *data; uchar *p; char *arg; void (*fmt)(Biobuf*, char*, ulong); int npr, x, y, nb, bpp; ulong v, mask; Rectangle r; fmt = nil; arg = nil; switch(img->depth){ case 1: case 2: case 4: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.1ux"; break; case 8: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.2ux"; break; case 16: arg = nil; if(img->chan == RGB16) fmt = Bprintr5g6b5; else{ fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.4ux"; } break; case 24: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.6lux"; break; case 32: fmt = (void(*)(Biobuf*,char*,ulong))Bprint; arg = "%.8lux"; break; } if(fmt == nil){ fprint(2, "bad format\n"); abort(); } r = img->r; Binit(&b, 2, OWRITE); data = vdata; bpp = img->depth; Bprint(&b, "%s\t%d\tr %R clipr %R repl %d data %p *%P\n", name, r.min.x, r, img->clipr, (img->flags&Frepl) ? 1 : 0, vdata, labelpt); mask = (1ULL<<bpp)-1;// for(y=r.min.y; y<r.max.y; y++){ for(y=0; y<Yrange; y++){ nb = 0; v = 0; p = data+(byteaddr(img, Pt(0,y))-(uchar*)img->data->bdata); Bprint(&b, "%-4d\t", y);// for(x=r.min.x; x<r.max.x; x++){ for(x=0; x<Xrange; x++){ if(x==0) Bprint(&b, "\t"); if(x != 0 && (x%8)==0) Bprint(&b, " "); npr = 0; if(x==labelpt.x && y==labelpt.y){ Bprint(&b, "*"); npr++; } if(npr == 0) Bprint(&b, " "); while(nb < bpp){ v &= (1<<nb)-1; v |= (ulong)(*p++) << nb; nb += 8; } nb -= bpp;// print("bpp %d v %.8lux mask %.8lux nb %d\n", bpp, v, mask, nb); fmt(&b, arg, (v>>nb)&mask); } Bprint(&b, "\n"); } Bterm(&b);}/* * Verify that the destination pixel has the specified value. * The value is in the high bits of v, suitably masked, but must * be extracted from the destination Memimage. */voidcheckone(Point p, Point sp, Point mp){ int delta; uchar *dp, *sdp; delta = (uchar*)byteaddr(dst, p)-(uchar*)dst->data->bdata; dp = (uchar*)dst->data->bdata+delta; sdp = (uchar*)savedstbits+delta; if(memcmp(dp, sdp, (dst->depth+7)/8) != 0) { fprint(2, "dtest: one bad pixel drawing at dst %P from source %P mask %P\n", p, sp, mp); fprint(2, " %.2ux %.2ux %.2ux %.2ux should be %.2ux %.2ux %.2ux %.2ux\n", dp[0], dp[1], dp[2], dp[3], sdp[0], sdp[1], sdp[2], sdp[3]); fprint(2, "addresses dst %p src %p mask %p\n", dp, byteaddr(src, sp), byteaddr(mask, mp)); dumpimage("src", src, src->data->bdata, sp); dumpimage("mask", mask, mask->data->bdata, mp); dumpimage("origdst", dst, dstbits, p); dumpimage("dst", dst, dst->data->bdata, p); dumpimage("gooddst", dst, savedstbits, p); abort(); }}/* * Verify that the destination line has the same value as the saved line. */#define RECTPTS(r) (r).min.x, (r).min.y, (r).max.x, (r).max.yvoidcheckline(Rectangle r, Point sp, Point mp, int y, Memimage *stmp, Memimage *mtmp){ ulong *dp; int nb; ulong *saved; dp = wordaddr(dst, Pt(0, y)); saved = savedstbits + y*dst->width; if(dst->depth < 8) nb = Xrange/(8/dst->depth); else nb = Xrange*(dst->depth/8); if(memcmp(dp, saved, nb) != 0){ fprint(2, "dtest: bad line at y=%d; saved %p dp %p\n", y, saved, dp); fprint(2, "draw dst %R src %P mask %P\n", r, sp, mp); dumpimage("src", src, src->data->bdata, sp); if(stmp) dumpimage("stmp", stmp, stmp->data->bdata, sp); dumpimage("mask", mask, mask->data->bdata, mp); if(mtmp) dumpimage("mtmp", mtmp, mtmp->data->bdata, mp); dumpimage("origdst", dst, dstbits, r.min); dumpimage("dst", dst, dst->data->bdata, r.min); dumpimage("gooddst", dst, savedstbits, r.min); abort(); }}/* * Fill the bits of an image with random data. * The Memimage parameter is used only to make sure * the data is well formatted: only ucbits is written. */voidfill(Memimage *img, uchar *ucbits){ int i, x, y; ushort *up; uchar alpha, r, g, b; void *data; if((img->flags&Falpha) == 0){ up = (ushort*)ucbits; for(i=0; i<nbytes/2; i++) *up++ = lrand() >> 7; if(i+i != nbytes) *(uchar*)up = lrand() >> 7; }else{ data = img->data->bdata; img->data->bdata = ucbits; for(x=img->r.min.x; x<img->r.max.x; x++) for(y=img->r.min.y; y<img->r.max.y; y++){ alpha = rand() >> 4; r = rand()%(alpha+1); g = rand()%(alpha+1); b = rand()%(alpha+1); putpixel(img, Pt(x,y), rgbatopix(r,g,b,alpha)); } img->data->bdata = data; } }/* * Mask is preset; do the rest */voidverifyonemask(void){ Point dp, sp, mp; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dp.x = nrand(Xrange); dp.y = nrand(Yrange); sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); drawonepixel(dst, dp, src, sp, mask, mp); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); memmove(savedstbits, dst->data->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, Rect(dp.x, dp.y, dp.x+1, dp.y+1), src, sp, mask, mp, SoverD); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); checkone(dp, sp, mp);}voidverifyone(void){ int i; /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; i<niters; i++) verifyonemask(); /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; i<niters; i++) verifyonemask(); /* random mask */ for(i=0; i<niters; i++){ fill(mask, maskbits); verifyonemask(); }}/* * Mask is preset; do the rest */voidverifylinemask(void){ Point sp, mp, tp, up; Rectangle dr; int x; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dr.min.x = nrand(Xrange-1); dr.min.y = nrand(Yrange-1); dr.max.x = dr.min.x + 1 + nrand(Xrange-1-dr.min.x); dr.max.y = dr.min.y + 1; sp.x = nrand(Xrange); sp.y = nrand(Yrange); mp.x = nrand(Xrange); mp.y = nrand(Yrange); tp = sp; up = mp; for(x=dr.min.x; x<dr.max.x && tp.x<Xrange && up.x<Xrange; x++,tp.x++,up.x++) memimagedraw(dst, Rect(x, dr.min.y, x+1, dr.min.y+1), src, tp, mask, up, SoverD); memmove(savedstbits, dst->data->bdata, dst->width*sizeof(ulong)*Yrange); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memimagedraw(dst, dr, src, sp, mask, mp, SoverD); checkline(dr, drawrepl(src->r, sp), drawrepl(mask->r, mp), dr.min.y, nil, nil);}voidverifyline(void){ int i; /* mask all ones */ memset(maskbits, 0xFF, nbytes); for(i=0; i<niters; i++) verifylinemask(); /* mask all zeros */ memset(maskbits, 0, nbytes); for(i=0; i<niters; i++) verifylinemask(); /* random mask */ for(i=0; i<niters; i++){ fill(mask, maskbits); verifylinemask(); }}/* * Mask is preset; do the rest */voidverifyrectmask(void){ Point sp, mp, tp, up; Rectangle dr; int x, y; fill(dst, dstbits); fill(src, srcbits); memmove(dst->data->bdata, dstbits, dst->width*sizeof(ulong)*Yrange); memmove(src->data->bdata, srcbits, src->width*sizeof(ulong)*Yrange); memmove(mask->data->bdata, maskbits, mask->width*sizeof(ulong)*Yrange); dr.min.x = nrand(Xrange-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -