机器视觉入门之路(一,认识位图处理类CDib,c++)

就是这个.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;iNumberOfColors ;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;

你可能感兴趣的:(机器视觉入门(一))