写在前面
BMP的相关基础见下面的博客:
这篇是为了实战读取一张BMP图像并将读完的数据写入另一幅BMP图,借此巩固一下对于BMP的理解和对文件操作相关函数的使用。
相关函数使用可见博客:http://t.csdnimg.cn/9nXDF
读取BMP
函数的声明如下:
static bool ReadBmp(unsigned char *pDib, string filename, int Width, int Height);
我期望这种函数可以在不创建类的对象的情况下直接通过类名来调用,所以用static来定义为静态成员函数,它与类本身关联而不是与类的对象关联。
函数的定义如下:
bool CBmpHelper::ReadBmp(unsigned char* pDib, string filename, int Width, int Height)
{
#ifdef WIN32
FILE *fpi = NULL;
BITMAPINFOHEADER pBmpInfo;
try
{
fpi = fopen(filename.c_str(), "rb");
if (fpi != NULL)
{
WORD bfType;
fread(&bfType, 1, sizeof(WORD), fpi);
if (0x4d42 != bfType)
{
return false;
}
fseek(fpi, sizeof(BITMAPFILEHEADER), 0);
cout<<sizeof(BITMAPFILEHEADER)<<endl;
fread(&pBmpInfo, 1, sizeof(BITMAPINFOHEADER), fpi);
cout << sizeof(BITMAPINFOHEADER) << endl;
fread(pDib, 1, Width * Height * 3, fpi);
fclose(fpi);
}
else
{
return false;
}
}
catch (...)
{
}
#endif
return true;
}
在打开文件之后,首先读取前两个字节,看看文件是否是BMP格式。
注意:fread读取,fpi位置会相应移动。
之后跳过文件头,读取信息头数据。
读完信息头,读取图像原始数据。
函数使用如下:
string filename = "bmp\\test.bmp";
int width = 280;
int height = 700;
unsigned char* pDib = new unsigned char[width * height * 3];
if (CBmpHelper::ReadBmp(pDib, filename, width, height))
{
cout << "读取BMP成功" << endl;
}
else
{
cout << "读取bmp失败" << endl;
}
写入BMP
函数声明如下:
static bool WriteBmp(unsigned char* pDib, string filename, int Width, int Height);
函数定义如下:
bool CBmpHelper::WriteBmp(unsigned char* pDib, string filename, int Width, int Height)
{
#ifdef WIN32
BITMAPFILEHEADER bfHdr{};
bfHdr.bfType = 0x4D42;//头文件类型 BMP 文件标志
bfHdr.bfReserved1 = 0;
bfHdr.bfReserved2 = 0;//两个预留字段设为0
bfHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//位图数据开始位置,一般为54
bfHdr.bfSize = Width * Height * 3 + bfHdr.bfOffBits;
int nInfoHeadSize = sizeof(BITMAPINFOHEADER);
LPBITMAPINFO pBmpInfo = (LPBITMAPINFO)new char[nInfoHeadSize];
pBmpInfo->bmiHeader.biSize = nInfoHeadSize;//信息头大小,一般为40byte
pBmpInfo->bmiHeader.biWidth = Width;//图像宽度
pBmpInfo->bmiHeader.biHeight = Height;//图像高度
pBmpInfo->bmiHeader.biPlanes = 1;//色彩平面的数量,必须为1
pBmpInfo->bmiHeader.biBitCount = 24;//图像深度
pBmpInfo->bmiHeader.biCompression = BI_RGB;//位图压缩类型
pBmpInfo->bmiHeader.biSizeImage = Width * Height * 3;//实际的位图数据占用的字节数
pBmpInfo->bmiHeader.biXPelsPerMeter = 0;//横向分辨率
pBmpInfo->bmiHeader.biYPelsPerMeter = 0;//纵向分辨率
pBmpInfo->bmiHeader.biClrUsed = 0;//调色板中颜色数量
pBmpInfo->bmiHeader.biClrImportant = 0;//重要颜色数量通常为0,表示每种颜色都重要
try
{
FILE* fpi = NULL;
fpi = fopen(filename.c_str(), "wb");
if (fpi != NULL)
{
fwrite(&bfHdr, 1, sizeof(BITMAPFILEHEADER), fpi);
fwrite(pBmpInfo, 1, sizeof(BITMAPINFOHEADER), fpi);
fwrite(pDib, 1, Width * Height * 3, fpi);
fclose(fpi);
}
else
{
return false;
}
}
catch (...)
{
}
delete[] pBmpInfo;
pBmpInfo = NULL;
#endif // WIN32
return true;
}
函数使用如下:
string filewrite = "bmp\\write.bmp";
if (CBmpHelper::WriteBmp(pDib,filewrite,width,height))
{
cout << "写入BMP成功" << endl;
}
else
{
cout << "写入bmp失败" << endl;
}
注释已经很详细了,这边不做过多解释。
运行后会在bmp文件夹下生成一张write的bmp图,内容与test一致。