C语言控制鼠标自动画图

最近在研究windows的鼠标自动控制程序,前面也写过一篇这方面的博客,今天又在基本控制的基础上加上了一些好玩的东西,那就是在画图软件中自动画图,是不是很炫酷。

基本思路是既然我们已经能控制鼠标的移动和点击了,那只要能打开画图软件,至少能在上面胡乱画些点和线。但是,乱画没什么意义啊,能不能画点有意思的东西呢?答案当然是肯定的了。既然画图那就画点好看的图片,好看的图片可以去百度下载,也可以是你朋友或者亲戚的照片,只要让我们的程序照着这张图片画不就ok了,图片的信息其实就是一些行列像素点,每个像素点由若干表示颜色的字节组成,以24位图为例,每个像素点包含3个字节,分别表示R、G、B,只要我们的程序能读取到这些信息,它就认识了这张图片,就可以照着图片画出相同的样子了。为了简单起见,我们先画黑白色调的图,这样就需要将图片进行二值化,二值化就是把每个像素点用0和1来表示,我采用的二值化算法是(R+G+B)/3的值小于128就取0,反之就取1。这样只要是0的点我们就把鼠标移动到相应的位置,然后点击就画出了一个点,而值为0的点无操作。这样一幅黑白照片就诞生了。

这里有几点注意事项,一是windows默认图片的行是4字节对齐的,对于不满足的行,会自动补充几个字节,而这几个字节是没有意义的,必须要过滤掉才能画出准确的图片,不然多几个点的图断行就会出现偏差,导致整张图片会有倾斜。我一开始就在这里栽了跟头,弄了好久才搞明白。二是画点的速度不能太快,太快了画图软件会反应不过来,他会错误得认为两次点击是一次点击,这样就会画出一条线,而不是我要的两个点,我的实验结果是两次画点间隔至少要2ms。

下面是读取图片并二值化得到一个维数组和图片宽和高的函数

int getMapArray(char *mapname, unsigned char *maparray, int* mapwidth, int* mapheight){
	int bytes = 3;//24位图
	BITMAPFILEHEADER fh;
	BITMAPINFOHEADER ih;
	int Row,Col;
	int i,j,k;
	int added;
	int index=0;
	FILE *f,*p;
	unsigned char *imagearray=(unsigned char*)calloc(6000*6000,sizeof(unsigned char));
	unsigned char *imagearray_tmp=(unsigned char*)calloc(6000*6000,sizeof(unsigned char));
	if((f=fopen(mapname,"rb"))==NULL){
		printf("open %s error,please check\n",mapname);
		return 0;
	}
	fread(&fh,sizeof(BITMAPFILEHEADER),1,f);
	if(fh.bfType!='MB')
	{
		printf("This is not a BMP picture, type is %s\n",fh.bfType);
		return 0;
	}
	
	fh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
	fread(&ih,sizeof(BITMAPINFOHEADER),1,f);
	mapheight[0]=Row=ih.biHeight;
	mapwidth[0]=Col=ih.biWidth;
	added = 4-(Col*bytes)%4;
	printf("added = %d\n",added);
	if(Row>2000||Col>2000){
		printf("BMP picture is too large, please cheese a small one, row=%d col=%d\n",Row,Col);
		return -1;
	}

	//每个像素点用3个字节表示(RGB),windows 会将图片的每一行4字节补齐,所以会多出一些字节,必须过滤掉这些字节
	fread(imagearray_tmp,sizeof(unsigned char),Row*(Col+1)*bytes,f);
	
	//过滤补齐的点
	for(i=0;i<Row*(Col*bytes+added);i++){
		for(j=0;j<added;j++){
			if(i%(Col*3+added)==Col*3+j) i++;
		}
		imagearray[index++] = imagearray_tmp[i];
	}
		
	//二值化
	int sum;
	index = 0;
	for(i=0;i<Row*(Col*bytes+added);i+=bytes){
		sum = 0;
		for(j=0;j<bytes;j++){
			sum+=imagearray[i+j];
		}
		if(sum/3<100)
			maparray[index++]=0;
		else
			maparray[index++]=1;
	}
	
	fclose(f);
	return 0;
}

主函数的功能就是调用上面的函数,得到图片信息,再调用move和click函数对鼠标进行操作画出图片,move和click函数在我的上一篇博客中已经贴出了代码,main函数代码如下:
int main(int argc,char *argv[]){
	int mapwidth[1];
	int mapheight[1];
	int i=0;
	int x=0;
	int y=0;
	int speed;//0:fast;1:namal;2:slow
	int tmp;
	char* mapname = argv[1];
	unsigned char* maparray=(unsigned char*)calloc(2000*2000,sizeof(unsigned char));
	if(argv[2]==NULL){
		speed=2;
	}
	else{
		tmp = atoi(argv[2]);
		if(tmp==1)
			speed=5;
		else if(tmp==2)
			speed=10;
		else
			speed=2;
	}
		
	getMapArray(mapname, maparray, mapwidth, mapheight);

	system("start /b C:/Windows/system32/mspaint.exe");

	int startx = (1920-mapwidth[0])/2;
	int starty = (1080+mapheight[0])/2;
	move(startx,starty);
	for(i=0;i<mapheight[0]*mapwidth[0];i++){
		if(maparray[i]==0){
			x = startx+i%mapwidth[0];
			y = starty-i/mapwidth[0];
			move(x,y);
			click(0,false);
			Sleep(speed);
		}
	}
	
	return 0;
	
}

最后贴上成果


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值