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

📄 nrotate.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * Rotate an image 180° in O(log Dx + log Dy) * draw calls, using an extra buffer the same size * as the image. * * The basic concept is that you can invert an array by * inverting the top half, inverting the bottom half, and * then swapping them. *  * This is usually overkill, but it speeds up slow remote * connections quite a bit. */#include <u.h>#include <libc.h>#include <bio.h>#include <draw.h>#include <event.h>#include "page.h"int ndraw = 0;enum {	Xaxis,	Yaxis,};static void reverse(Image*, Image*, int);static void shuffle(Image*, Image*, int, int, Image*, int, int);static void writefile(char *name, Image *im, int gran);static void halvemaskdim(Image*);static void swapranges(Image*, Image*, int, int, int, int);/* * Rotate the image 180° by reflecting first * along the X axis, and then along the Y axis. */voidrot180(Image *img){	Image *tmp;	tmp = xallocimage(display, img->r, img->chan, 0, DNofill);	if(tmp == nil)		return;	reverse(img, tmp, Xaxis);	reverse(img, tmp, Yaxis);	freeimage(tmp);}Image *mtmp;static voidreverse(Image *img, Image *tmp, int axis){	Image *mask;	Rectangle r;	int i, d;	/*	 * We start by swapping large chunks at a time.	 * The chunk size should be the largest power of	 * two that fits in the dimension.	 */	d = axis==Xaxis ? Dx(img) : Dy(img);	for(i = 1; i*2 <= d; i *= 2)		;	r = axis==Xaxis ? Rect(0,0, i,100) : Rect(0,0, 100,i);	mask = xallocimage(display, r, GREY1, 1, DTransparent);	mtmp = xallocimage(display, r, GREY1, 1, DTransparent);	/*	 * Now color the bottom (or left) half of the mask opaque.	 */	if(axis==Xaxis)		r.max.x /= 2;	else		r.max.y /= 2;	draw(mask, r, display->opaque, nil, ZP);	writefile("mask", mask, i);	/*	 * Shuffle will recur, shuffling the pieces as necessary	 * and making the mask a finer and finer grating.	 */	shuffle(img, tmp, axis, d, mask, i, 0);	freeimage(mask);}/* * Shuffle the image by swapping pieces of size maskdim. */static voidshuffle(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim){	int slop;	if(maskdim == 0)		return;	/*	 * Figure out how much will be left over that needs to be	 * shifted specially to the bottom.	 */	slop = imgdim % maskdim;	/*	 * Swap adjacent grating lines as per mask.	 */	swapadjacent(img, tmp, axis, imgdim - slop, mask, maskdim);	/*	 * Calculate the mask with gratings half as wide and recur.	 */	halvemaskdim(mask, maskdim, axis);	writefile("mask", mask, maskdim/2);	shuffle(img, tmp, axis, imgdim, mask, maskdim/2);	/*	 * Move the slop down to the bottom of the image.	 */	swapranges(img, tmp, 0, imgdim-slop, imgdim, axis);	moveup(im, tmp, lastnn, nn, n, axis);}/* * Halve the grating period in the mask. * The grating currently looks like  * ####____####____####____####____ * where #### is opacity. * * We want * ##__##__##__##__##__##__##__##__ * which is achieved by shifting the mask * and drawing on itself through itself. * Draw doesn't actually allow this, so  * we have to copy it first. * *     ####____####____####____####____ (dst) * +   ____####____####____####____#### (src) * in  __####____####____####____####__ (mask) * =========================================== *     ##__##__##__##__##__##__##__##__ */static voidhalvemaskdim(Image *m, int maskdim, int axis){	Point δ;	δ = axis==Xaxis ? Pt(maskdim,0) : Pt(0,maskdim);	draw(mtmp, mtmp->r, mask, nil, mask->r.min);	gendraw(mask, mask->r, mtmp, δ, mtmp, divpt(δ,2));	writefile("mask", mask, maskdim/2);}/* * Swap the regions [a,b] and [b,c] */static voidswapranges(Image *img, Image *tmp, int a, int b, int c, int axis){	Rectangle r;	Point δ;	if(a == b || b == c)		return;	writefile("swap", img, 0);	draw(tmp, tmp->r, im, nil, im->r.min);	/* [a,a+(c-b)] gets [b,c] */	r = img->r;	if(axis==Xaxis){		δ = Pt(1,0);		r.min.x = img->r.min.x + a;		r.max.x = img->r.min.x + a + (c-b);	}else{		δ = Pt(0,1);		r.min.y = img->r.min.y + a;		r.max.y = img->r.min.y + a + (c-b);	}	draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, b)));	/* [a+(c-b), c] gets [a,b] */	r = img->r;	if(axis==Xaxis){		r.min.x = img->r.min.x + a + (c-b);		r.max.x = img->r.min.x + c;	}else{		r.min.y = img->r.min.y + a + (c-b);		r.max.y = img->r.min.y + c;	}	draw(img, r, tmp, nil, addpt(tmp->r.min, mulpt(δ, a)));	writefile("swap", img, 1);}/* * Swap adjacent regions as specified by the grating. * We do this by copying the image through the mask twice, * once aligned with the grading and once 180° out of phase. */static voidswapadjacent(Image *img, Image *tmp, int axis, int imgdim, Image *mask, int maskdim){	Point δ;	Rectangle r0, r1;	δ = axis==Xaxis ? Pt(1,0) : Pt(0,1);	r0 = img->r;	r1 = img->r;	switch(axis){	case Xaxis:		r0.max.x = imgdim;		r1.min.x = imgdim;		break;	case Yaxis:		r0.max.y = imgdim;		r1.min.y = imgdim;	}	/*	 * r0 is the lower rectangle, while r1 is the upper one.	 */	draw(tmp, tmp->r, img, nil, }voidinterlace(Image *im, Image *tmp, int axis, int n, Image *mask, int gran){	Point p0, p1;	Rectangle r0, r1;	r0 = im->r;	r1 = im->r;	switch(axis) {	case Xaxis:		r0.max.x = n;		r1.min.x = n;		p0 = (Point){gran, 0};		p1 = (Point){-gran, 0};		break;	case Yaxis:		r0.max.y = n;		r1.min.y = n;		p0 = (Point){0, gran};		p1 = (Point){0, -gran};		break;	}	draw(tmp, im->r, im, display->black, im->r.min);	gendraw(im, r0, tmp, p0, mask, mask->r.min);	gendraw(im, r0, tmp, p1, mask, p1);}static voidwritefile(char *name, Image *im, int gran){	static int c = 100;	int fd;	char buf[200];	snprint(buf, sizeof buf, "%d%s%d", c++, name, gran);	fd = create(buf, OWRITE, 0666);	if(fd < 0)		return;		writeimage(fd, im, 0);	close(fd);}

⌨️ 快捷键说明

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