您的位置:首页 > 其它

VC/MFC中位图保存的实现方法

2014-09-18 23:24 537 查看
在MFC中位图操作,经常要涉及到关于位图的保存,通常有两种思路,一种是往DIB类(用户自己建立的位图操作类)添加SaveBmp函数,另外一种直接往视类添加位图保存函数OnSave。

(1)通常来说,采用往DIB类中添加位图保存函数,更符合C++面向对象的思想,即将对对象的处理函数封装在一个类中,编程的条理性也更好。不足之处是,如果在位图上绘制图形时,如矩形、椭圆等图形,调用位图保存函数时,绘制的图形并未保存。这是因为MFC中采用的文档/视图类的结构,文档仅处理数据的读写操作,数据保存在文档类的成员变量中。视图从文档类中将文档的数据取出来,然后再屏幕上显示文档的数据。直接调用DIB类中的SaveBmp,只能保存位图的数据,而无法把绘制的图形连同位图一起保存。

附代码如下:

BOOL CDib::SaveBmp(LPCTSTR filename)
{

	//写模式打开文件   
	CFile file;
	if (!file.Open (filename ,CFile::modeCreate |CFile ::modeReadWrite |CFile ::shareExclusive ))
		return FALSE ;
	//求取颜色表和位图数据大小
	int m_nColorTableLength =GetNumberOfColors ();
	int BitCount=m_pBitmapInfoHeader->biBitCount;
	//保证待存储图像数据每行字节数为4的倍数
	int lineByte=(GetWidth ()*BitCount+31)/32*4;
	DWORD bmpDataSize=lineByte*GetHeight ();
	m_pData = pDib + m_pBitmapInfoHeader->biSize+ sizeof (RGBQUAD )*m_nColorTableLength;
	try {
		//文件头结构写进文件
		file.Write (&bitmapFileHeader ,sizeof(BITMAPFILEHEADER ));
		//文件信息头写入文件
		file.Write(m_pBitmapInfoHeader ,sizeof(BITMAPINFOHEADER ));
		//如果有颜色表,颜色表写进文件
		if (m_nColorTableLength !=0)
			file.Write (m_pRGB ,sizeof (RGBQUAD )*m_nColorTableLength );
		//位图数据写进文件
		file.Write (m_pData ,bmpDataSize );
	}
	catch (CException * pe){
		pe->Delete ();
		AfxMessageBox ("write error!");
		return FALSE;
	}
	file .Close ();
	return TRUE;
}

(2)往****View视类中添加OnSave函数可以完美的解决这一问题,因为其保存图片的思想是根据MFC工作区位图的位置、大小,对工作区制定位置的图形进行完完整整的复制,由于复制的是屏幕上工作区的图案,故人为绘制的图形可以保存。此处参照了360个人图书馆的一个链接。
http://www.360doc.com/content/12/1203/10/9133899_251714845.shtml
附代码如下:

<span style="font-size:14px;">//位图的保存
	void CDrawView::OnFileSave()
	{
		// TODO: 在此添加命令处理程序代码
		//--------------------------------------------------------
		//保存位图:可以保存工作区上的图片,不仅可以保存原有的位图文件,还可以保存在位图上绘制的图形
		//--------------------------------------------------------
		CClientDC  dc(this); 
		CDC   memDC;
		memDC.CreateCompatibleDC(&dc);   
		CBitmap   bm; 
		CRect rect;
		GetClientRect (&rect );
		int   Width   = bmp_width;    
		int   Height   =bmp_height; 
		bm.CreateCompatibleBitmap(&dc,   Width,   Height);   
		CBitmap*     pOld   =   memDC.SelectObject(&bm);   
		memDC.BitBlt(0 ,  0 ,   Width,   Height,   &dc,   xorigin,   yorigin,   SRCCOPY);   
		memDC.SelectObject(pOld);   
		BITMAP     btm;   
		bm.GetBitmap(&btm);   
		DWORD     size   =   btm.bmWidthBytes   *   btm.bmHeight;   
		LPSTR   lpData   =   (LPSTR)GlobalAlloc(GPTR,   size);   
		BITMAPFILEHEADER       bfh;   
		BITMAPINFOHEADER     bih;   
		bih.biBitCount   =   btm.bmBitsPixel;   
		bih.biClrImportant   =   0;   
		bih.biClrUsed   =   0;   
		bih.biCompression   =   0;   
		bih.biHeight   =   btm.bmHeight;   
		bih.biPlanes   =   1;   
		bih.biSize   =   sizeof(BITMAPINFOHEADER);   
		bih.biSizeImage   =   size;   
		bih.biWidth   =   btm.bmWidth;   
		bih.biXPelsPerMeter   =   0;   
		bih.biYPelsPerMeter   =   0;   
		GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);   
		bfh.bfReserved1   =   bfh.bfReserved2   =   0;   
		bfh.bfType   =   ((WORD)('M'<<   8)|'B');   //bfh.bfType=0x4D42;//bmp类型
		bfh.bfSize   =   54   +   size;   
		bfh.bfOffBits   =   54;   
		CFileDialog   dlg(false,_T("BMP"),_T("*.bmp"),OFN_HIDEREADONLY   |   OFN_OVERWRITEPROMPT,_T("*.bmp|*.bmp|*.*|*.*|"));   
		if   (dlg.DoModal()!=IDOK)   
			return;   

		CFile     bf;   
		CString   ss=dlg.GetPathName();   
		if(bf.Open(ss,   CFile::modeCreate   |   CFile::modeWrite))   
		{   
			bf.Write(&bfh,sizeof(BITMAPFILEHEADER));   
			bf.Write(&bih,sizeof(BITMAPINFOHEADER));   
			bf.Write(lpData,   size);   
			bf.Close();   
		}   
		GlobalFree(lpData);
		AfxMessageBox ("图片保存成功!");
		SaveFlag =TRUE ;
		
	}</span>


附效果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: