一、所用到的流处理函数:
fstream:可同时进行读写操作的文件类;或
ofstream:写操作(从内存中读数据到文件)的文件类;
ifstream:读操作(从文件读数据到内存)的文件类。
二、位图文件的格式:
① 位图文件头,所用结构体:BITMAPFILEHEADER,占14个字节
② 位图信息头,所用结构体:BITMAPINFOHEADER,占40个字节
③ 颜色表项,所用结构体:RGBQUAD,由biBitCount值决定
④ 数据区,当结构体BITMAPINFOHEADER中的成员变量
biBitCount = 1时,1个字节代表8个像素;
biBitCount = 2时,1个字节代表2个像素;
biBitCount = 8时,1个字节代表1个像素;
biBitCount = 16时,2个字节代表1个像素;
biBitCount = 24时,3个字节代表1个像素;
RGBQUAD结构体的定义如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色分量
BYTE rgbGreen; // 绿色分量
BYTE rgbRed; // 红色分量
BYTE rgbReserved; // 保留值,必须为0.
} RGBQUAD;
即一个RGBQUAD结构体占4个字节,
当biBitCount = 1,2,4,8时,颜色表项分别占2,4,16,256个RGBQUAD结构体大小的空间;
当biBitCount = 24时,③颜色表项不占空间,即位图文件只有①②④三项,这是因为数据区中3个字节代表一个像素,本身含有三原色分量值。
三、需要注意的问题:
1. bmp数据存储时按行从左到右、按列从下到上扫描,所以对于24位bmp文件,数据区前三个字节代表位图左下角第一个元素;
2. bmp文件存储的图片数据每行所占的字节数都是4的整数倍,不够的用0补充,所以有
biSizeImage = ((((bi.Width*bitBitCount)+31)&~31)/8)*bi.biHeight
3. 对于24位bmp文件,若图片每行像素所占字节数满足是4的整数倍这个条件,由于BITMAPFILEHEADER和BITMAPINFOHEADER所占的总字节数为54,不是4的倍数,所以补0后为56字节。
四、方法一:
BOOL Cprogram2Dlg::RGB2GRAY(CString strPath)
{
fstream Infile;
fstream Outfile;
BITMAPFILEHEADER bfheader = {0};
BITMAPINFOHEADER biheader;
unsigned char *src;
unsigned char *dst;
// 打开与创建
Infile.open("In_Picture.bmp",ios::binary|ios::in);
Outfile.open("Out_ Picture.bmp",ios::binary|ios::out);
// 读取文件头与信息头
Infile.read((char*)& bfheader,sizeof(bmp_fileheader));
Infile.read((char*)& biheader,sizeof(bmp_infoheader));
// 开辟空间载入内存
src = new unsigned char[biheader.biHeight* biheader.biWidth*3];
Infile.read((char*)src,sizeof(unsignedchar)* biheader.biHeight* biheader.biWidth*3);
// 彩色转灰度像素处理,可在此加入图像处理算法
dst = new unsigned char[biheader.biHeight* biheader.biWidth*3];
int tmp;
unsigned long j = 0;
for (unsigned long i = 0;i < biheader.biHeight* biheader.biWidth*3;i += 3)
{
tmp = (src[i]+src[i+1]+src[i+2])/3;
dst[j++]=(unsigned char)tmp;
dst[j++]=(unsigned char)tmp;
dst[j++]=(unsigned char)tmp;
}
// 写文件头与信息头
Outfile.write((char*)& bfheader,sizeof(bmp_fileheader));
Outfile.write((char*)& biheader,sizeof(bmp_infoheader));
Outfile.write((char*)dst,sizeof(unsigned char)* biheader.biWidth* biheader.biHeight*3);
delete[] src;
delete[] dst;
return TRUE;
}
五、方法二:
BOOL Cprogram2Dlg::PictureProcessing(CString strPath)
{
//fstream input_file;
//fstream output_file;
bmp_fileheader bfh = {0};
bmp_infoheader bih;
unsigned char *src_buff;
unsigned char *dst_buff;
FILE *fpin = fopen("In_Picture.bmp","rb");
FILE *fpout = fopen("Out_Picture.bmp","wb");
if(fpin == NULL || fpout == NULL) return 0;
fread(&bfh,sizeof(bmp_fileheader),1,fpin);
fread(&bih,sizeof(bmp_infoheader),1,fpin);
src_buff = new unsigned char[bih.biHeight*bih.biWidth*3];
fread(src_buff,sizeof(unsigned char),bih.biHeight*bih.biWidth*3,fpin);
dst_buff = new unsigned char[bih.biHeight*bih.biWidth*3];
int tmp;
unsigned long j = 0;
for (unsigned long i = 0;i < bih.biHeight*bih.biWidth*3;i += 3)
{
tmp = (src_buff[i]+src_buff[i+1]+src_buff[i+2])/3;
dst_buff[j++]=(unsigned char)tmp;
dst_buff[j++]=(unsigned char)tmp;
dst_buff[j++]=(unsigned char)tmp;
}
fwrite(&bfh,sizeof(bmp_fileheader),1,fpout);
fwrite(&bih,sizeof(bmp_infoheader),1,fpout);
fwrite(dst_buff,sizeof(unsigned char),bih.biWidth*bih.biHeight*3,fpout);
delete[] src_buff;
delete[] dst_buff;
return TRUE;
}