第三题:位图放缩
使用双线性插值法
设计思路
- 使用结构体创建位图文件的头文件和信息头;
- 从命令行获取文件名,创建文件流;
- 按照放缩比例修改位图文件头和位图信息头中相关的数据(分辨率等);
- 创建指针存储位图数据,就是像素颜色数据;
- 双线性插值法处理放缩后的图像颜色;
- 将得到的新数据写入目标位图文件.
具体实现
全局声明
使用伪指令让结构体以一个字节对齐,能正确获取结构体占有的内存;
使用位图中的名词声明类型;
#pragma pack(1)
typedef unsigned char BYTE;
typedef unsigned short int WORD;
typedef unsigned int DWORD;
typedef int LONG;
- 位图文件头的定义:
//14字节的文件头
typedef struct tagBITMAPFILEHEADER{
WORD bfType; //2字节,文件类型
DWORD bfSize; //4字节,文件大小
WORD bfReserved1,bfReserved2; //2字节,保留,必须设置为0
DWORD bfOffBits; //4字节,从头到位图数据的偏移
}BITMAPFILEHEADER;
位图信息头的定义:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //4字节,信息头的大小
LONG biWidth,biHeight; //biWidth:4字节,以像素为单位说明图像的宽度;
//biHeight:4字节,以像素为单位说明图像的高度,同时如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向;
WORD biPlanes; //2字节,为目标设备说明颜色平面数,总被设置为1
WORD biBitCount; //2字节,说明比特数/像素数,值有1、2、4、8、16、24、32
DWORD biCompression; //4字节,说明图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩
DWORD biSizeImages; //4字节,说明位图数据的大小,当用BI_RGB格式时,可以设置为0
LONG biXPelsPerMeter; //表示水平分辨率,单位是像素/米,有符号整数
LONG biYPelsPerMeter; //表示垂直分辨率,单位是像素/米,有符号整数
DWORD biClrUsed; //说明位图使用的调色板中的颜色索引数,为0说明使用所有
DWORD biClrImportant; //明对图像显示有重要影响的颜色索引数,为0说明都重要
}BITMAPINFOHEADER;
- 命令行中的第二、第四个参数是原文件名和目标文件名,第三个参数是放缩比例;
char *filename,*result;
filename=argv[1]; //原文件名
result=argv[3]; //目标文件名
FILE *fp;
fp=fopen(filename,"rb");
FILE *rp;
rp=fopen(result,"wb");
char *op;
op=argv[2]; //放缩百分比
double a=(double)atoi(op)/100; //百分比化成小数
- 位图文件头和位图信息头中的数据修改;
BITMAPFILEHEADER src_fh,src_re_fh; //用于储存文件头
BITMAPINFOHEADER src_ih,src_re_ih; //用于储存信息头
fread(&src_fh,sizeof(BITMAPFILEHEADER),1,fp);
fread(&src_ih,sizeof(BITMAPINFOHEADER),1,fp);
unsigned int filename_size;
filename_size=src_ih.biHeight*src_ih.biWidth; //得到原图的像素大小
//文件头和信息头基本类似,先copy
src_re_fh=src_fh;
src_re_ih=src_ih;
src_re_ih.biHeight=(LONG)(src_ih.biHeight*a); //目标位图的高
src_re_ih.biWidth=(LONG)(src_ih.biWidth*a); //目标位图的宽
unsigned int result_size=src_re_ih.biWidth*src_re_ih.biHeight; //目标图的像素大小
src_re_fh.bfSize=54+result_size*sizeof