BMP图片的读取与写入【学习笔记】
BMP图片的格式
按照数据的存储顺序:
1.14个字节的文件头
2. 40个字节的图像信息头
3. 调色板数据(24位BMP图片可不包含调色板)
4. 图像数据
在C++中,文件头,图像信息头,调色板所包含的成员已经被封装在了结构体中,无需自己定义。关于BMP图片格式的详细分析请参照bmp文件格式详细解析
fread与fwrite
fread 与fwrite 中各个参数的意义:
第一个参数const void _str:存储要读取或写入数据的变量。
第二个参数size_t_size: 一条数据的长度。
第三个参数size_t_count: 共有多少条数据。
第四个参数 FILE_file: 文件指针
BMP文件的读取
以8位BMP图片为例
FILE *fp;
int linebyte;//图像数据总个数
BITMAPFILEHEADER Header;//存储文件头
BITMAPINFOHEADER Info//存储信息头
RGBQUAD *Quadbuff//存储调色板数据
if((fp = fopen(url,"rb"))==NULL)
{
cout<<"The file: "<<url<<" can't be opened"<<endl;
system("pause");
}
fread(&Header,sizeof(BITMAPFILEHEADER),1,fp);
fread(&Info,sizeof(BITMAPINFOHEADER),1,fp);
Quadbuff = new RGBQUAD[256];
fread(Quadbuff,sizeof(RGBQUAD),256,fp);//注意,这里Quadbuff是数组,不能再取地址,否则读取的东西是错误的
linebyte = (Info.biWidth*Info.biBitCount/8+3)/4*4;//数据总长度
m_Width = linebyte;//图像宽度
m_Hight = Info.biHeight;//图像高度
m_Buffer = new unsigned char[linebyte*img.m_Hight];//开辟存储空间,存储图像数据
fread(m_Buffer,sizeof(char),linebyte*m_Hight,fp);//这里同Ouadbuff
fclose(fp);
以上是读取八位BMP图片的方法,依照存储顺序,先读取文件头,再读取信息头,再读调色板,最后读数据。
24位BMP图片与之类似,区别在于:
- 24位没有调色板,不需要read 调色板,直接read 图像数据
- 8位bmp的图像数据实际上是调色板颜色的索引值,因此每个像素仅有1位(占一个字节)。而24位bmp由于不存再调色板,所以每个像素需要3位来存储,即存三个数据是一个像素值(蓝,绿,红各占一个数据位),所以再read图像数据时要开辟3倍像素个数的空间。
BMP文件的写入
写入与读取类似,先写入文件头,然后一次写入信息头,调色板,图像数据。文件头和信息头中的变量值可自己定义,也可以事先存好,自己定义是请详细了解各个属性的意义。同样以8位BMP为例,文件头,信息头以及调色板应用上面读取时的保存值。
FILE *fpw;
if((fpw = fopen(filename,"wb")) == NULL)
{
cout<<"write file false"<<endl;
return FALSE;
}
//fwrite(&bfType,1,sizeof(bfType),fpw);
unsigned char * rgbBuff;
rgbBuff = new unsigned char[size];
for(int i=0;i<size;i++)
{
rgbBuff[i] = (unsigned char)img.data[i];
} ///要保存的图像数据
fwrite(&Header,sizeof(BITMAPFILEHEADER),1, fpw); //写入文件头
fwrite(&Info,sizeof(BITMAPINFOHEADER),1, fpw);//写入信息头
fwrite(I.quadbuff,sizeof(RGBQUAD),256,fpw);//写入调色板
fwrite(rgbBuff,sizeof(char),size,fpw);//写入数据
fclose(fpw);