⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mug.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <cursor.h>#define initstate muginitstatetypedef struct State State;struct State {	double black;	double white;	double stretch;	double gamma;	int depth;	int gtab[1001];	Rectangle selr;};typedef struct Face Face;struct Face {	Rectangle r;	State state;	Image *small;};double GAMMA = 1.0;		/* theory tells me this should be 2.2, but 1.0 sure looks better */enum {	Left=0,	Right,	Top,	Bottom,	RTopLeft=0,	RTop,	RTopRight,	RLeft,	RMiddle,	RRight,	RBotLeft,	RBot,	RBotRight,};void*emalloc(ulong sz){	void *v;	v = malloc(sz);	if(v == nil)		sysfatal("malloc %lud fails\n", sz);	memset(v, 0, sz);	return v;}Face *face[8];int nface;uchar grey2cmap[256];Image *bkgd;Image *orig;Image *ramp, *small, *osmall, *tmp8, *red, *green, *blue;State state, ostate;uchar val2cmap[256];uchar clamp[3*256];Rectangle rbig, rramp, rface[nelem(face)], rsmall;double *rdata;int sdy, sdx;voidgeometry(Rectangle r){	int i;	Rectangle fr[9];	rramp.min = addpt(r.min, Pt(4,4));	rramp.max = addpt(rramp.min, Pt(256,256));	rbig.min = Pt(rramp.max.x+6, rramp.min.y);	rbig.max = addpt(rbig.min, Pt(Dx(orig->r), Dy(orig->r)));	for(i=0; i<9; i++)		fr[i] = rectaddpt(Rect(0,0,48,48), Pt(rramp.min.x+48+56*(i%3), rramp.max.y+6+56*(i/3)));	rsmall = fr[4];	for(i=0; i<4; i++)		rface[i] = fr[i];	for(i=4; i<8; i++)		rface[i] = fr[i+1];}doubley2gamma(int y){	double g;	g = (double)y / 128.0;	return 0.5+g*g;		/* gamma from 0.5 to 4.5, with 1.0 near the middle */}intgamma2y(double g){	g -= 0.5;	return (int)(128.0*sqrt(g)+0.5);}voiddrawface(int i){	if(i==-1){		border(screen, rsmall, -3, blue, ZP);		draw(screen, rsmall, small, nil, ZP);		return;	}	border(screen, rface[i], -1, display->black, ZP);	if(face[i])		draw(screen, rface[i], face[i]->small, nil, ZP);	else		draw(screen, rface[i], display->white, nil, ZP);}voiddrawrampbar(Image *color, State *s){	Rectangle liner, r;	static Rectangle br;	if(Dx(br))		draw(screen, br, ramp, nil, subpt(br.min, rramp.min));	r = rramp;	r.max.x = r.min.x + (int)(s->white*255.0);	r.min.x += (int)(s->black*255.0);	r.min.y += gamma2y(s->gamma);	r.max.y = r.min.y+1; 	rectclip(&r, rramp);	draw(screen, r, color, nil, ZP);	br = r;	r.min.y -= 2;	r.max.y += 2;		liner = r;	r.min.x += Dx(liner)/3;	r.max.x -= Dx(liner)/3;	rectclip(&r, rramp);	draw(screen, r, color, nil, ZP);	combinerect(&br, r);	r = liner;	r.max.x = r.min.x+3;	rectclip(&r, rramp);	draw(screen, r, color, nil, ZP);	combinerect(&br, r);	r = liner;	r.min.x = r.max.x-3;	rectclip(&r, rramp);	draw(screen, r, color, nil, ZP);	combinerect(&br, r);}voiddrawscreen(int clear){	int i;	if(clear){		geometry(screen->r);		draw(screen, screen->r, bkgd, nil, ZP);	}	border(screen, rbig, -1, display->black, ZP);	draw(screen, rbig, orig, nil, orig->r.min);	border(screen, rramp, -1, display->black, ZP);	draw(screen, rramp, ramp, nil, ramp->r.min);	drawrampbar(red, &state);	border(screen, rectaddpt(state.selr, subpt(rbig.min, orig->r.min)), -2, red, ZP);	if(clear){		drawface(-1);		for(i=0; i<nelem(face); i++)			drawface(i);	}}voidmoveframe(Rectangle old, Rectangle new){	border(screen, rectaddpt(old, subpt(rbig.min, orig->r.min)), -2, orig, old.min);	border(screen, rectaddpt(new, subpt(rbig.min, orig->r.min)), -2, red, ZP);}/* * Initialize gamma ramp; should dither for * benefit of non-true-color displays. */voidinitramp(void){	int k, x, y;	uchar dat[256*256];	double g;	k = 0;	for(y=0; y<256; y++) {		g = y2gamma(y);		for(x=0; x<256; x++)			dat[k++] = 255.0 * pow(x/255.0, g);	}	assert(k == sizeof dat);	ramp = allocimage(display, Rect(0,0,256,256), GREY8, 0, DNofill);	if(ramp == nil)		sysfatal("allocimage: %r");	if(loadimage(ramp, ramp->r, dat, sizeof dat) != sizeof dat)		sysfatal("loadimage: %r");}voidinitclamp(void){	int i;	for(i=0; i<256; i++) {		clamp[i] = 0;		clamp[256+i] = i;		clamp[512+i] = 255;	}}voidchangestretch(double stretch){	state.stretch = stretch;}/* * There is greyscale data for the rectangle datar in data; * extract square r and write it into the 48x48 pixel image small. */voidprocess(double *data, Rectangle datar, Rectangle r, Image *small){	double black, center, delta, *k, shrink, sum, *tmp[48], *tt, w, white, x;	int datadx, dp, dx, dy, error, i, ii, j, jj;	int ksize, ksizeby2, sdata[48*48], sd, sh, sm, sv, u, uu, uuu, v, vv;	uchar bdata[48*48];	datadx = Dx(datar);	dx = Dx(r);	dy = Dy(r);	shrink = dx/48.0;	ksize = 1+2*(int)(shrink/2.0);	if(ksize <= 2)		return;	k = emalloc(ksize*sizeof(k[0]));	/* center of box */	for(i=1; i<ksize-1; i++)		k[i] = 1.0;	/* edges */	x = shrink - floor(shrink);	k[0] = x;	k[ksize-1] = x;	sum = 0.0;	for(i=0; i<ksize; i++)		sum += k[i];	for(i=0; i<ksize; i++)		k[i] /= sum;	ksizeby2 = ksize/2;	for(i=0; i<48; i++)		tmp[i] = emalloc(datadx*sizeof(tmp[i][0]));	/* squeeze vertically */	for(i=0; i<48; i++) {		ii = r.min.y+i*dy/48;		tt = tmp[i];		uu = ii - ksizeby2;		for(j=r.min.x-ksize; j<r.max.x+ksize; j++) {			if(j<datar.min.x || j>=datar.max.x)				continue;			w = 0.0;			uuu = uu*datadx+j;			if(uu>=datar.min.y && uu+ksize<datar.max.y)				for(u=0; u<ksize; u++){					w += k[u]*data[uuu];					uuu += datadx;				}			else				for(u=0; u<ksize; u++){					if(uu+u>=datar.min.y && uu+u<datar.max.y)						w += k[u]*data[uuu];					uuu+=datadx;				}			tt[j-datar.min.x] = w;		}	}	/* stretch value scale */	center = (state.black+state.white)/2;	delta = state.stretch*(state.white-state.black)/2;	black = center - delta;	white = center + delta;	/* squeeze horizontally */	for(i=0; i<48; i++) {		tt = tmp[i];		for(j=0; j<48; j++) {			jj = r.min.x+j*dx/48;			w = 0.0;			for(v=0; v<ksize; v++) {				vv = jj - ksizeby2 + v;				if(vv<datar.min.x || vv>=datar.max.x) {					w += k[v];		/* assume white surround */					continue;				}				w += k[v]*tt[vv-datar.min.x];			}			if(w < black || black==white)				w = 0.0;			else if(w > white)				w = 1.0;			else				w = (w-black)/(white-black);			sdata[i*48+j] = state.gtab[(int)(1000.0*w)];		}	}	/* dither to lower depth before copying into GREY8 version */	if(small->chan != GREY8) {		u = 0;		dp = small->depth;		for(i=0; i<48; i++) {			sm = 0xFF ^ (0xFF>>dp);			sh = 0;			v = 0;			for(j=0; j<48; j++) {				ii = 48*i+j;				sd = clamp[sdata[ii]+256];				sv = sd&sm;				v |= sv>>sh;				sh += dp;				if(sh == 8) {					bdata[u++] = v;					v = 0;					sh = 0;				}				/* propagate error, with decay (sum errors < 1) */				error = sd - sv;				if(ii+49 < 48*48) {	/* one test is enough, really */					sdata[ii+1] = sdata[ii+1]+((3*error)>>4);					sdata[ii+48] = sdata[ii+48]+((3*error)>>4);					sdata[ii+49] = sdata[ii+49]+((3*error)>>3);				}				/* produce correct color map value by copying bits */				switch(dp){				case 1:					sv |= sv>>1;				case 2:					sv |= sv>>2;				case 4:					sv |= sv>>4;				}				sdata[ii] = sv;			}		}		for(i=0; i<nelem(bdata); i++)			bdata[i] = sdata[i];		if(loadimage(tmp8, tmp8->r, bdata, sizeof bdata) != sizeof bdata)			sysfatal("loadimage: %r");		draw(small, small->r, tmp8, nil, tmp8->r.min);	} else {		for(i=0; i<nelem(bdata); i++)			bdata[i] = sdata[i];		if(loadimage(small, small->r, bdata, sizeof bdata) != sizeof bdata)			sysfatal("loadimage: %r");	}	free(k);	for(i=0; i<48; i++)		free(tmp[i]);}voidinitval2cmap(void){	int i;	for(i=0; i<256; i++)		val2cmap[i] = rgb2cmap(i, i, i);}voidsetgtab(State *s){	int i;	for(i=0; i<=1000; i++)		s->gtab[i] = val2cmap[(int)(255.0*pow((i/1000.0), 1.0/s->gamma))];}intsection(int x){	int ib, iw;	ib = state.black * 255.0;	iw = state.white * 255.0;	if(x<ib-5 || iw+5<x)		return -1;	iw -= ib;	x -= ib;	if(x < iw/3)		return 0;	if(x < 2*iw/3)		return 1;	return 2;}Image*copyimage(Image *i){	Image *n;	if(i == nil)		return nil;	n = allocimage(display, i->r, i->chan, 0, DNofill);	if(n == nil)		sysfatal("allocimage: %r");	draw(n, n->r, i, nil, i->r.min);	return n;}Image*grey8image(Image *i){	Image *n;	if(i->chan == GREY8)		return i;	n = allocimage(display, i->r, GREY8, 0, DNofill);	if(n == nil)		sysfatal("allocimage: %r");	draw(n, n->r, i, nil, i->r.min);	freeimage(i);	return n;}voidmark(void){	if(osmall != small){		freeimage(osmall);		osmall = small;	}	ostate = state;}voidundo(void){	if(small != osmall){		freeimage(small);		small = osmall;	}	state = ostate;	process(rdata, orig->r, state.selr, small);	drawface(-1);	drawscreen(0);}voidsaveface(Face *f, int slot){	if(slot == -1){		mark();		state = f->state;		small = copyimage(f->small);		drawface(-1);		drawscreen(0);		return;	}	if(face[slot]==nil)		face[slot] = emalloc(sizeof(*face[slot]));	else{		freeimage(face[slot]->small);		face[slot]->small = nil;	}	if(f == nil){		face[slot]->small = copyimage(small);		face[slot]->state = state;	}else{		face[slot]->small = copyimage(f->small);		face[slot]->state = f->state;	}	drawface(slot);}intwriteface(char *outfile, Image *image){	int i, fd, rv, y;	uchar data[48*48/2];	if(outfile == nil)		fd = 1;	else{		if((fd = create(outfile, OWRITE, 0666)) < 0) 			return -1;	}	switch(image->chan) {	default:		rv = -1;		break;	case GREY1:		if(unloadimage(image, image->r, data, 48*48/8) != 48*48/8)			sysfatal("unloadimage: %r");		for(y=0; y<48; y++) {			for(i=0; i<3; i++)				fprint(fd, "0x%.2x%.2x,", data[y*6+i*2+0], data[y*6+i*2+1]);			fprint(fd, "\n");		}		rv = 0;		break;			case GREY2:		if(unloadimage(image, image->r, data, 48*48/4) != 48*48/4)			sysfatal("unloadimage: %r");		for(y=0; y<48; y++) {			for(i=0; i<3; i++)				fprint(fd, "0x%.2x%.2x,%.2x%.2x,",					data[y*12+i*4+0], data[y*12+i*4+1],					data[y*12+i*4+2], data[y*12+i*4+3]);			fprint(fd, "\n");		}		rv = 0;		break;	case GREY4:	case GREY8:		rv = writeimage(fd, image, 0);	/* dolock? */		break;	}	if(outfile)		close(fd);	return rv;}voidroom(Rectangle out, Rectangle in, int *a){	a[Left] = out.min.x - in.min.x;	a[Right] = out.max.x - in.max.x;	a[Top] = out.min.y - in.min.y;	a[Bottom] = out.max.y - in.max.y;}intmin(int a, int b){	if(a < b)		return a;	return b;}intmax(int a, int b){	if(a > b)		return a;	return b;}intmove(Rectangle r, Rectangle picr, Point d, int k, Rectangle *rp){	int a[4], i;	Rectangle oldr;	static int toggle;	oldr = r;	room(picr, r, a);	switch(k){	case RTopLeft:		i = (d.x+d.y)/2;		if(i>=Dx(r) || i>=Dy(r))			break;		i = max(i, a[Left]);		i = max(i, a[Top]);		r.min.x += i;		r.min.y += i;		break;	case RTop:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -