显示位图

来源:互联网 发布:windows whistler2267 编辑:程序博客网 时间:2024/05/16 02:13

一。显示位图,需要做如下工作:

void  类名::ShowMap()

{

CStatic* pStatic=(CStatic*)GetDlgItem(IDC_DISPLAY2);///据待贴位图的控件ID得到它的控制对象。
CDC* pDC=pStatic->GetDC();//待贴位图的控件的dc
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP2);
BITMAP bmp;
bitmap.GetBitmap(&bmp);//获得位图信息结构体。
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);//兼容DC创建。dcCompatible.SelectObject(&bitmap);
CRect rect;
pStatic->GetClientRect(&rect);

pDC->StretchBlt(0,0,rect.Width(),rect.Height(), &dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

pStatic->ReleaseDC(pDC);

///如果直接是所在类的控件上,可以用CClientDC de(this);获得dc;

}

 

二。通过读位图文件数据来显示位图,我以660*500大小24位图解说。

void  类名::ShowMap()

{

CClientDC dc(this);
 BYTE (*pf)[660][3]=new BYTE[500][660][3];

//信息写入内存,[3]代表本位图一个像素用三个字节表示颜色信息,r,g,b;


 CFile file("provc.bmp",CFile::modeRead );
 file.Seek(45,CFile::begin );//跳过文件头结构的大小,后面才是颜色数据。
 file.Read(pf,660*500*3);

 for (int i=0;i<660;++i)//循环,从左到右绘点。
 {
   for (int j=0;j<500;++j)
  {
   dc.SetPixel(i,j,RGB(pf[499-j][i][0],pf[499-j][i][1],pf[499-j][i][2]));
  }
  }
 delete []pf;

}

 

三。位图信息处理

处理位图的时候,获得的是一个指向内存中一块区域的指针pData,这块区域中存储着图像的灰度值。而如果要处理加载的位图,也需要获取其位图数据的指针。因此两者的处理方法是差不多的。这里就以处理加载的位图为例进行说明。

要获取位图数据的指针,可以使用GetBitmapBits(),而要将处理后的数据COPY到位图对象中,则使用SetBitmapBits(),如果位图是24的,它的一个像素数据占3个字节,分别表示RGB。因此,如果这幅位图宽度是1000个像素,那么其字节宽度就是3000个字节。一般的图像处理都是针对灰度图像,也就是说一个像素的RGB值是相等的,从黑色(0,0,0)到白色(255,255,255)变化。因此,我处理图像的时候,只需要处理它的像素数据的代表R的字节,然后代表G和B的字节就都等于R的值就可以了。下面是代码:

BYTE *pmydata;    //定义一个指针用来指向位图图像数据在内存中的存储区域
pmydata=new BYTE[bmp.bmWidthBytes*bmp.bmHeight];   //根据位图的高度宽度初始化一下
bitmap.GetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,pmydata); //将位图对象的数据COPY到pmydata指向的区域,bitmap是位图对象,bmp是位图结构,可参考上一篇文章的定义
for(int i=0;i<bmp.bmWidthBytes*bmp.bmHeight;i+=3) //这里只是将RGB三个字节的值取平均值,再取个反
{                                                                    //因为一个像素有3个字节,故i+=3
   BYTE temp=0;
   temp=(pmydata[i]+pmydata[i+1]+pmydata[i+2])/3;
   pmydata[i]=255-temp;//R值
   pmydata[i+1]=255-temp;//G值
   pmydata[i+2]=255-temp;//B值
}

这样就实现了图像数据的简单处理,然后将处理的数据COPY回位图对象:

bitmap.SetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,pmydata); //将处理后的数据COPY进位图对象

随后按照上一篇文章的步骤显示位图即可。

 

注:对于图像采集上来的灰度值数据,一个像素只有一个字节,如果图像的像素数据是4个字节,可巧用COLORREF数组:

COLORREF* m_ColorData=new COLORREF[width*height];

这个COLORREF实际上就是DWORD,上面这句话定义了一个指向一块存放DWORD类型的数据的指针,也就是说,m_ColorData[i]与m_ColorData[i+1]之间有4个字节的距离,这正好与32位位图的像素数据存放方式相对应。将灰度值数据处理好之后,转化成RGB值:

//将灰度值转换为RGB值进行显示
   for(i=0;i<width*height;i++)   
    m_ColorData[i]=RGB( m_bytes[i], m_bytes[i], m_bytes[i]);

其中的m_bytes[i]就是灰度值,上面这句话的意思是将m_ColorData[i]的四个字节中的前三个字节赋值为:m_bytes[i], m_bytes[i], m_bytes[i]。然后建立一个位图对象bitmap,使用SetBitmapBits()函数设置它的图像数据的值。

bitmap.SetBitmapBits(width*height*sizeof(COLORREF),m_ColorData);。然后按照前面说的步骤将这个位图对象显示处理即可。

 

小说下:

COLORREF类型用来描绘一个RGB颜色。其定义如下:

  typedef DWORD COLORREF;

可以用这样一个结构体来描述。

  RGB_value struct

  {

  byte unused ;

  byte blue ;

  byte green ;

  byte red;

  };

  其中第一字节为 而且始终为 0,其它三个字节分别表示兰色、绿色和红色,刚好和 RGB 的次序相反。这个结构体用起来挺别扭。对于COLORREF,我们通常使用宏RGB对其进行赋值。

  宏的定义如下:

  COLORREF RGB

  (

  BYTEbyRed, // red component of color

  BYTEbyGreen, // green component of color

  BYTEbyBlue // blue component of color

  );

COLORREF 是一个 32-bit 整型数值,代表了一种颜色。用 RGB 函数来初始化 COLORREF

如: COLORREF color=RGB(0,255,0);

原创粉丝点击