C语言实现bmp图像几何变换(移动,旋转,镜像,转置,缩放)

C语言实现bmp图像几何变换(移动,旋转,镜像,转置,缩放)

自定义结构及函数如下:

#define pi 3.1415926
typedef struct {
	unsigned char bfType[2];
	unsigned long bfSize;
	unsigned short bfReserved1;
	unsigned short bfReserved2;
	unsigned long bfOffBits;
}bitmapFileHeader;

typedef struct {
	unsigned long biSize;
	unsigned long biWidth;
	unsigned long biHeight;
	unsigned short biPlanes;
	unsigned short biBitCount;
	unsigned long biCompression;
	unsigned long biSizeImage;
	long biXPixPerMeter;
	long biYPixPerMeter;
	unsigned long biClrUsed;
	unsigned long biClrImportant;
}bitmapInfoHeader;

/*
typedef struct{
	unsigned char rgbBlue;
	unsigned char rgbGreen;
	unsigned char rgbRed;
	unsigned rgbReserved;
}rgbQUAD;
*/
//这里没有考虑有调色板的位图
//如果是保存有调色板的位图的话,需要更改这个结构体
typedef struct{
	bitmapFileHeader bfHeader;
	bitmapInfoHeader biHeader;
	unsigned char *imgData;
}bmp;

double fmax(double a,double b){
	if(a>b)
		return a;
	else 
		return b;
}

涉及bmp图像读取和保存代码:

    //bmp图像读取
	bmp b;
	b.imgData=(unsigned char*)malloc(sizeof(unsigned char)*imSize);
	memset(b.imgData,0,sizeof(unsigned char)*imSize);
	memcpy(&(b.bfHeader),&bfHeader,sizeof(bfHeader));
	memcpy(&(b.biHeader),&biHeader,sizeof(biHeader));
	
	//bmp图像保存
	char savePath[]="D:\Temp\\save_test.bmp";
	FILE *f=fopen(savePath,"wb");
	if(f==NULL){
		perror("can not open file!");
		return -2;
	}
	fwrite(&b.bfHeader,sizeof(bitmapFileHeader),1,f);
	fwrite(&b.biHeader,sizeof(bitmapInfoHeader),1,f);
	fwrite(b.imgData,sizeof(unsigned char)*b.biHeader.biSizeImage,1,f);
	fclose(f);

使用的图像:
在这里插入图片描述
在这里插入图片描述

移动

int xOffset=100,yOffset=100;
	if(width<xOffset||height<yOffset)
		return -1;
	for(int i=0;i<height;i++){
		for(int j=0;j<width*3;j++){
			if(i+yOffset<height&&i+yOffset>=0&&j+xOffset*3<width*3&&j+xOffset*3>=0)
				b.imgData[lineBytes*(i+yOffset)+j+xOffset*3]=imageData[lineBytes*i+j];
		}
	}

在这里插入图片描述

旋转

	//对图像进行旋转
	double angle=pi/3;
	double half_w=width/2.0,half_h=height/2.0;
	double cosa=cos(angle),sina=sin(angle);
	double x1=-half_w*cosa+ half_h*sina,y1=half_w*sina+half_h*cosa;
	double x2=half_w*cosa+half_h*sina,y2=-half_w*sina+half_h*cosa;
	double x3=-half_w*cosa-half_h*sina,y3=half_w*sina-half_h*cosa;
	double x4=half_w*cosa-half_h*sina,y4=-half_w*sina-half_h*cosa;

	int width_new=(int)(fmax(fabs(x4-x1),fabs(x3-x2))+0.5);
	int height_new=(int)(fmax(fabs(y4-y1),fabs(y3-y2))+0.5);

	int lineBytes_new=(width_new*bitCount+31)/32*4;
	b.biHeader.biWidth=width_new;
	b.biHeader.biHeight=height_new;
	b.biHeader.biSizeImage=lineBytes_new*height_new;
	b.bfHeader.bfSize=54+lineBytes_new*height_new;
	b.imgData=(unsigned char*)realloc(b.imgData,lineBytes_new*height_new*sizeof(unsigned char));
	memset(b.imgData,0,lineBytes_new*height_new*sizeof(unsigned char));

	double const1=-width_new*cosa/2.0+height_new*sina/2.0+width/2.0;
	double const2=-width_new*sina/2.0-height_new*cosa/2.0+height/2.0;
	
	int x0,y0;
	for(int i=0;i<height_new;i++){
		for(int j=0;j<width_new;j++){
			x0=(int)(j*cosa-i*sina+const1+0.5);
			y0=(int)(j*sina+i*cosa+const2+0.5);
			if(x0>=0&&x0<width&&y0>=0&&y0<height){
				b.imgData[lineBytes_new*i+j*3]=imageData[lineBytes*y0+x0*3];
				b.imgData[lineBytes_new*i+j*3+1]=imageData[lineBytes*y0+x0*3+1];
				b.imgData[lineBytes_new*i+j*3+2]=imageData[lineBytes*y0+x0*3+2];
			}
		}
	}

在这里插入图片描述

镜像

//镜像
	for(int i=0;i<height;i++){
		for(int j=0;j<width*3;j++){
			b.imgData[lineBytes*i+j]=imageData[lineBytes*(height-1-i)+j];
		}
	}

在这里插入图片描述

转置

	int lineBytes_new=(height*bitCount+31)/32*4;
	b.biHeader.biWidth=height;
	b.biHeader.biHeight=width;
	b.biHeader.biSizeImage=width*lineBytes_new*sizeof(unsigned char);
	b.bfHeader.bfSize=54+width*lineBytes_new*sizeof(unsigned char);
	b.imgData=(unsigned char*)realloc(b.imgData,lineBytes_new*width*sizeof(unsigned char));
	memset(b.imgData,0,width*lineBytes_new*sizeof(unsigned char));
	
	for(int i=0;i<height;i++){
		for(int j=0;j<width;j++){
			b.imgData[lineBytes_new*(width-1-j)+(height-1-i)*3]=imageData[lineBytes*i+j*3];
			b.imgData[lineBytes_new*(width-1-j)+(height-1-i)*3+1]=imageData[lineBytes*i+j*3+1];
			b.imgData[lineBytes_new*(width-1-j)+(height-1-i)*3+2]=imageData[lineBytes*i+j*3+2];
		}
	}

在这里插入图片描述

缩放

//缩放
	double ratio=2.0;
	int width_new=(int)(width*ratio+0.5),height_new=(int)(height*ratio+0.5);
	int lineBytes_new=(width_new*bitCount+31)/32*4;
	b.biHeader.biWidth=width_new;
	b.biHeader.biHeight=height_new;
	b.biHeader.biSizeImage=height_new*lineBytes_new*sizeof(unsigned char);
	b.bfHeader.bfSize=54+height_new*lineBytes_new*sizeof(unsigned char);
	b.imgData=(unsigned char*)realloc(b.imgData,height_new*lineBytes_new*sizeof(unsigned char));
	memset(b.imgData,0,height_new*lineBytes_new*sizeof(unsigned char));
	
	int x0,y0;
	for(int i=0;i<height_new;i++){
		for(int j=0;j<width_new;j++){
			x0=(int)(j/ratio);
			y0=(int)(i/ratio);
			if(x0>=0&&x0<width&&y0>=0&&y0<height){
				b.imgData[lineBytes_new*i+j*3]=imageData[lineBytes*y0+x0*3];
				b.imgData[lineBytes_new*i+j*3+1]=imageData[lineBytes*y0+x0*3+1];
				b.imgData[lineBytes_new*i+j*3+2]=imageData[lineBytes*y0+x0*3+2];
			}
		}
	}

在这里插入图片描述

  • 21
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值