MP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。
本示例主要实现24位真彩色BMP图片的放大与缩小。采用的缩放算法为双线性插值。
双线性插值参考链接:https://blog.csdn.net/weixinhum/article/details/38963705
[xsw@xsw BMP_stady]$ ./a.out 1.bmp watermark.bmp
源图片宽:504
源图片高:314
请输入要放大或缩小的倍数(放大为正数,缩小为负数):-1
放大或缩小的比例超出范围,请重新输入!
请输入要放大或缩小的倍数(放大为正数,缩小为负数):0.5
新图片宽:756
新图片高:471
缩放比例:150%
[xsw@xsw BMP_stady]$
[xsw@xsw BMP_stady]$ gcc zoom.c
[xsw@xsw BMP_stady]$ ./a.out
格式:./a.out
[xsw@xsw BMP_stady]$ ./a.out 1.bmp watermark.bmp
源图片宽:504
源图片高:314
请输入要放大或缩小的倍数(放大为正数,缩小为负数):-0.25
新图片宽:378
新图片高:235
缩放比例:75%
[xsw@xsw BMP_stady]$
/*****************************BMP图片放大缩小************************
**
**形参:const char *new_bmp -- 缩放后的图片名
** const char *socure_bmp -- 源图片名
**返回值:0 -- 成功; 其它值 -- 失败
*********************************************************************/
int BMP_ZoomInandOut(const char *new_bmp,const char *socure_bmp)
{
FILE *fp[2];
fp[0]=fopen(socure_bmp,"rb");//只读方式打开源图片
if(fp[0]==NULL)
{
printf("[%s line %d]文件打开失败",__FUNCTION__,__LINE__);
return 1;
}
fp[1]=fopen(new_bmp,"w+b");
if(fp[1]==NULL)
{
printf("[%s line %d]文件打开或创建失败",__FUNCTION__,__LINE__);
return 2;
}
BMP_HEADER bmp_head;
BMP_INFO bmp_info;
fread(&bmp_head,sizeof(BMP_HEADER),1,fp[0]);//读取头数据
if(bmp_head.bfType!=0x4d42)
{
printf("[%s line %d]图片格式错误\n",__FUNCTION__,__LINE__);
fclose(fp[0]);
fclose(fp[1]);
return 3;
}
fread(&bmp_info,sizeof(BMP_INFO),1,fp[0]);//读取位图数据
unsigned long w,h;
w=bmp_info.biWidth;//源图片宽
h=bmp_info.biHeight;//源图片高
printf("\t源图片宽:%d\n",w);
printf("\t源图片高:%d\n",h);
unsigned long oneline_byte=w*3;
while(oneline_byte%4)oneline_byte++;//源图片一行字节数,不是4的倍数补全
float zoom_count=0;
pp:
printf("\n\t请输入要放大或缩小的倍数(放大为正数,缩小为负数):");
scanf("%f",&zoom_count);
if(zoom_count<=-1|| zoom_count>4)
{
printf("放大或缩小的比例超出范围,请重新输入!\n");
goto pp;
}
bmp_info.biWidth=(1+zoom_count)*w;//新图片宽
bmp_info.biHeight=(1+zoom_count)*h;//新图片高
unsigned long new_w=bmp_info.biWidth;//新图片宽
unsigned long new_h=bmp_info.biHeight;//新图片高
printf("\t新图片宽:%d\n",new_w);
printf("\t新图片高:%d\n", new_h);
printf("\t缩放比例:%.0f%%\n",(new_w*1.0/w)*100);
unsigned long new_oneline_byte=new_w*3;
while(new_oneline_byte%4)new_oneline_byte++;//新图片一行字节数,不是4的倍数补全
// printf("新图片一行字节数:%d\n",new_oneline_byte);
bmp_head.bfSize=new_oneline_byte*new_h+sizeof(BMP_HEADER)+sizeof(BMP_INFO);//图片总大小
bmp_info.biSizeImage=new_oneline_byte*new_h;//位图大小
fwrite(&bmp_head,sizeof(BMP_HEADER),1,fp[1]);//头数据写入到新的文件中
fwrite(&bmp_info,sizeof(BMP_INFO),1,fp[1]);//位图数据写入到新的文件中
unsigned char *newbmp_buff=(unsigned char *)malloc(new_h*new_oneline_byte);//动态分配新图片RGB颜色数据缓冲区
if(newbmp_buff==NULL)
{
printf("[%s line %d]动态分配空间失败\n",__FUNCTION__,__LINE__);
fclose(fp[0]);
fclose(fp[1]);
return 4;
}
memset(newbmp_buff, 0, new_h*new_oneline_byte);
unsigned char *bmp_buff=(unsigned char *)malloc(h*oneline_byte);//动态分配新图片RGB颜色数据缓冲区
if(bmp_buff==NULL)
{
printf("[%s line %d]动态分配空间失败\n",__FUNCTION__,__LINE__);
fclose(fp[0]);
fclose(fp[1]);
return 5;
}
memset(bmp_buff, 0, h*oneline_byte);
unsigned long rgb_data_size=0;
rgb_data_size=h*oneline_byte;//源图片RGB颜色数据字节大小
fseek(fp[0],bmp_head.bfOffBits,SEEK_SET);//将文件指针偏移到RGB数据处
fread(bmp_buff,rgb_data_size,1,fp[0]);//读出所有颜色数据
/************************图像处理算法(双线性插值)*******************************/
int i,j;
for(i=0;i;i++)>
主函数
int main(int argc,char **argv)
{
if(argc!=3)
{
printf("格式:./a.out \n");
return 0;
}
int stat=0;
char buff[20];
stat=BMP_ZoomInandOut(argv[1],argv[2]);
if(stat==0)
{
snprintf(buff,sizeof(buff),"eog %s",argv[1]);//字符串拼接
system(buff);//创建进程
}
else printf("[%s line %d] err %d\n",__FUNCTION__,__LINE__,stat);
return 0;
}
BMP位图结构体
//位图文件头信息结构定义
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType; //保存图片类型。 'BM'
unsigned long bfSize; //图片文件的总大小,以字节为单位(3-6字节,低位在前)
unsigned short bfReserved1;//位图文件保留字,必须为0(7-8字节)
unsigned short bfReserved2;//位图文件保留字,必须为0(9-10字节)
unsigned long bfOffBits; //RGB数据偏移地址,位图数据的起始位置,以相对于位图(11-14字节,低位在前)//文件头的偏移量表示,以字节为单位
} BMP_HEADER;
//信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
typedef struct tagBITMAPINFOHEADER {
unsigned long biSize; //本结构所占用字节数(15-18字节)
unsigned long biWidth; //位图的宽度,以像素为单位(19-22字节)
unsigned long biHeight; //位图的高度,以像素为单位(23-26字节)
unsigned short biPlanes; //目标设备的级别,必须为1(27-28字节)
unsigned short biBitCount; //每个像素所需的位数,必须是1(双色)(29-30字节),4(16色),8(256色)16(高彩色)或24(真彩色)之一
unsigned long biCompression;//位图压缩类型,必须是0(不压缩),(31-34字节)
//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
unsigned long biSizeImage; //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
unsigned long biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节)
unsigned long biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节)
unsigned long biClrUsed; //位图实际使用的颜色表中的颜色数(47-50字节)
unsigned long biClrImportant; //位图显示过程中重要的颜色数(51-54字节)
} BMP_INFO;
注:本示例运行环境为32位redHat6.3 linux下实现,若是64位linux系统需要注意结构体大小。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !