就是这个.bmp位图,差一点把我挡在门外,所谓,万事开头难。
首先只是一个处理图像的想法,那么自己先要加载一个.bmp位图,瞅一瞅吧!
最初,会一点c++,知道一点.bmp位图,微软使用的图像格式。
书上,网上都有处理位图的cdib类,抄的我都快哭了!
下面,这是我那时删到最简单的cdib类:我们看还能否继续删除暂时不相关,
假定我们加载一幅640*480真彩色.bmp位图,那时的30万的摄像头所保存的图片(未压缩格式,24位=3*8)。
bool CDib::LoadBmp (LPCTSTR fn)//假定fn=c:\\自拍头像.bmp
{
if(fn==/*L*/"") return false;//如果字符串fn为空,返回
Free();
ifstream files(fn,ios::binary);//文件输入输出流格式为二进制
if(!files.is_open())
{
return false;//文件打开失败
}
files.read((LPSTR)&m_BmpFH ,sizeof(BITMAPFILEHEADER));//就像看小说,不懂先放过,其实他不重要
//第一次read,不是.bmp文件,返回
if(m_BmpFH.bfType !=this->BmpMarker )
{
return false;
}
DWORD bmpinfosz;
bmpinfosz=this->m_BmpFH .bfOffBits -sizeof(BITMAPFILEHEADER);
this->m_BmpInfo =(LPBITMAPINFO) new BYTE[bmpinfosz];//就像看小说,不懂先放过,其实他不重要
//第二次read,是.bmp文件的information(信息)
files.read((char *)this->m_BmpInfo ,bmpinfosz);
CalBmpData();
if(this->BPP<8||this->BPP>32)
{
Free();
return false;
}
this->m_Buffer =new BYTE[this->BufferSize ];
//第三次read,是.bmp文件的内容,放入buffer[]
files.read((char*)this->m_Buffer,this->BufferSize );
this->m_BmpLoaded =true;
return true;
}
比较关键的函数void CDib::CalBmpData ()//我们现在可以把调色板(RGBQUAD)删除了,还有谁用呢?
{
if(this->m_BmpInfo ==NULL)
return;
this->Width =this->m_BmpInfo ->bmiHeader .biWidth ;
this->Height =this->m_BmpInfo ->bmiHeader .biHeight ;
this->BPP =this->m_BmpInfo ->bmiHeader .biBitCount ;
this->Bpl =(this->Width *(this->BPP /8)+3)&~3;
this->BufferSize =this->Bpl *this->Height ;
//以下删除和调色板相关20200621
// if(this->BPP >=16||this->BPP <8)
// {
// this->NumberOfColors =0;
// return;
// }
// if(this->m_BmpInfo ->bmiHeader .biClrUsed ==0)
// {
// this->NumberOfColors =256;
// }
// else
// {
// this->NumberOfColors =this->m_BmpInfo ->bmiHeader .biClrUsed ;
// }
// this->m_Quad=new RGBQUAD[this->NumberOfColors ];
// for(DWORD i=0;i
// {
// this->m_Quad [i]=this->m_BmpInfo ->bmiColors [i];
// }
}
void CDib::Free()
{
if(this->m_Buffer)
{
delete [] m_Buffer;
this->m_Buffer =NULL;
}
if(this->m_BmpInfo )
{
delete [] m_BmpInfo;
this->m_BmpInfo =NULL;
}
// if(this->m_Quad )//继续删除20200621
// {
// delete [] m_Quad;
// this->m_Quad=NULL;
// }
}
再下来,就是构造函数和析构函数
CDib::CDib()
{
m_BmpLoaded=false;
m_Buffer=NULL;
m_BmpInfo=NULL;
// m_Quad=NULL;//继续干掉20200621
BmpMarker=('M'<<8)|'B';
Width=0;
Height=0;
}
CDib::~CDib()
{
Free();
}
以上是Hdib.cpp文件,好,在看一下头文件(Hdib.h)
class CDib//我们看一看,位图.bmp里有什么
{
public:
BYTE *m_Buffer;//第三次读的数据放这里
public:
// RGBQUAD *m_Quad;//不要了20200621
DWORD m_BmpLoaded;//位图加载成功,设置为true;
BITMAPFILEHEADER m_BmpFH;//这两个够你研究一壶的了
BITMAPINFO * m_BmpInfo;
DWORD Width;//图像的宽
DWORD Height;//图像的高
DWORD BPP;//在这里是24
DWORD BufferSize;//真彩色位图数据大小
DWORD Bpl;//每一行多少字节?
// DWORD NumberOfColors;//不要了20200621
WORD BmpMarker;//位图的标志
private:
void CalBmpData();
public:
void Free();
bool LoadBmp(LPCTSTR fn);
public:
CDib();
virtual ~CDib();
};
只要文件里的数据读入你的buffer,已经算是成功了。
当你对比c#之后,可能就不会再用c++的cdib了,但是,有时c#加载位图乱码错位,失败时,他就会起作用,它里边隐含了一个行要能被4整除的.bmp位图的规则,找找看?
下面是buffer行列数据在界面显示的代码,要用到微软的gdi+,我们下一节搞定
注意:hdib.h文件中包含
#include
#include
using namespace std;