C语言实现bmp图像几何变换(移动,旋转,镜像,转置,缩放)
程序员文章站
2022-04-07 17:51:28
...
自定义结构及函数如下:
#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];
}
}
}