Chinaunix首页 | 论坛 | 博客
  • 博客访问: 367940
  • 博文数量: 715
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:46
文章分类

全部博文(715)

文章存档

2011年(1)

2008年(714)

我的朋友

分类:

2008-10-13 16:40:06

VC实现自绘图形输出到bmp文件

作者:



  在用vc做程序时候,经常需要把输出的文本和图形保存到位图文件,当然可以有现成的控件来实现,但总不能如自己所愿,还是自己动手写吧!如下图:



一、实现方法

  要把文本和图形保存到位图文件,只要对掌握位图结构有一定的了解,一切都ok呢。先必须要创建内存设备环境,然后内存设备环境创建的DIB区域,别忘了还要创建个CBitmap对象,CBitmap对象必须和DIB区域关联起来,把CBitmap对象选择到当前设备环境,然后在当前设备环境输出文本和图形就可以了。

二、具体实现代码如下

void CTestSaveBmpView::SaveAsBmp(CString filename)
{
	//定义图形大小
	int iWidth = 800;
	int iHeight = 600;
	int iPixel = 16;
	//图形格式参数
	LPBITMAPINFO lpbmih = new BITMAPINFO;
	lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	lpbmih->bmiHeader.biWidth = iWidth;
	lpbmih->bmiHeader.biHeight = iHeight;
	lpbmih->bmiHeader.biPlanes = 1;
	lpbmih->bmiHeader.biBitCount = iPixel;
	lpbmih->bmiHeader.biCompression = BI_RGB;
	lpbmih->bmiHeader.biSizeImage = 0;
	lpbmih->bmiHeader.biXPelsPerMeter = 0;
	lpbmih->bmiHeader.biYPelsPerMeter = 0;
	lpbmih->bmiHeader.biClrUsed = 0;
	lpbmih->bmiHeader.biClrImportant = 0;
	
	//创建位图数据
	HDC hdc,hdcMem;
	HBITMAP hBitMap = NULL;
	CBitmap *pBitMap = NULL;
	CDC *pMemDC = NULL;
	BYTE *pBits;
	
	hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
	hdcMem = CreateCompatibleDC(hdc);
	hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_PAL_COLORS,(void **)&pBits,NULL,0);
	pBitMap = new CBitmap;
	pBitMap->Attach(hBitMap);
	pMemDC = new CDC;
	pMemDC->Attach(hdcMem);
	pMemDC->SelectObject(pBitMap);
	//
	CRect rc(0,0,iWidth,iHeight);
	pMemDC->SetBkMode(TRANSPARENT);
	//添加自绘图形 
	DrawCurve(pMemDC,rc);
	//保存到文件并创建位图结构
	BITMAPFILEHEADER bmfh;
	ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
	*((char *)&bmfh.bfType) = ''B'';
	*(((char *)&bmfh.bfType) + 1) = ''M'';
	bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	bmfh.bfSize = bmfh.bfOffBits + (iWidth * iHeight) * iPixel / 8;
	
	TCHAR szBMPFileName[128];
	int iBMPBytes = iWidth * iHeight * iPixel / 8;
	strcpy(szBMPFileName,filename);
	CFile file;
	if(file.Open(szBMPFileName,CFile::modeWrite | CFile::modeCreate))
	{
		file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
		file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
		file.Write(pBits,iBMPBytes);
		file.Close();
	}
	
	pMemDC->DeleteDC();
	delete pMemDC; pMemDC = NULL;
	delete pBitMap; pBitMap = NULL;
	delete lpbmih; lpbmih = NULL;
}

//输出文本和图形

void CTestSaveBmpView::DrawCurve(CDC *pDC, CRect rcClient)
{
	//页面背景色
	CBrush brushCtl;
	brushCtl.CreateSolidBrush(RGB(255,255,255));
	pDC->Rectangle(rcClient);
	pDC->FillRect(rcClient,&brushCtl) ;
	brushCtl.DeleteObject();
	
	CPen pen;
	pen.CreatePen(PS_SOLID, 1, RGB(255,0,0));
	CPen *oldPen = pDC->SelectObject(&pen); 
	
	double xMin = 10.00f, xMax = 100.00f;
	double yMin = 10.00f, yMax = 200.00f;
	
	double dbX1 = (xMax- xMin)/100 + xMin;
	double dbY1 = 600/dbX1 ;
	for (int i=1; i<100; i++) //曲线
	{
		double dbX2 = (xMax- xMin)*i/100 + xMin;
		double dbY2 = 600/dbX2 ;
		
		pDC->MoveTo(int(rcClient.left+(dbX1 - xMin)*rcClient.Width()/(xMax- xMin)), 
			int(rcClient.bottom-(dbY1- yMin)*rcClient.Height()/(yMax- yMin)));
		pDC->LineTo(int(rcClient.left+(dbX2 - xMin)*rcClient.Width()/(xMax- xMin)), 
			int(rcClient.bottom-(dbY2- yMin)*rcClient.Height()/(yMax- yMin))); 
		
		dbX1=dbX2;
		dbY1=dbY2;
	}
	pDC->SelectObject(oldPen); 
	pen.DeleteObject();
	oldPen = NULL;
}

//保存的实现
void CTestSaveBmpView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	
	CFileDialog dlg(false,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		"位图文件(*.bmp)|*.bmp|",
		NULL);
	if (dlg.DoModal()!= IDOK) return;
	CString filename = dlg.GetFileName() + ".bmp";
	SaveAsBmp(filename); 
	
	CView::OnRButtonDown(nFlags, point);
}





--------------------next---------------------

没看懂的人请看这一段
void CTestSaveBmpView::OnRButtonDown(UINT nFlags, CPoint point) 
{

CFileDialog dlg(false,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"位图文件(*.bmp)|*.bmp|All Files(*.*)|*.*||"
   ,NULL);
if (dlg.DoModal()!= IDOK) return;
CString filename = dlg.GetFileName() + ".bmp";
SaveAsBmp(filename);

CView::OnRButtonDown(nFlags, point);
}


意思是在屏幕上单击右键就出来对话框的意思

不是那个上面菜单里的save as

如果想改成菜单里面的,可以自已把上面的代码加到单击消息里,

没看懂的说明vc还在菜鸟级,哈哈
( xswyzao 发表于 2008-7-28 23:45:00)
 
用以下代码可以实现bmp格式保存

BOOL CBitmapDoc::OnSaveDocument(LPCTSTR lpszPathName) 
{
// TODO: Add your specialized code here and/or call the base class
if (m_pDibData == NULL)
return (FALSE);

CFile cf;

if(!cf.Open(lpszPathName, CFile::modeCreate | CFile::modeWrite))
return (FALSE);

try
{
BITMAPFILEHEADER BFH;
memset(&BFH, 0, sizeof(BITMAPFILEHEADER));
BFH.bfType = 'MB';
BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_DibSize;
BFH.bfOffBits = sizeof(BITMAPFILEHEADER) + 
sizeof(BITMAPINFOHEADER) + m_nColorTableNumber *sizeof(RGBQUAD);

cf.Write(&BFH, sizeof(BITMAPFILEHEADER));
cf.Write(m_pDibData, m_DibSize);
}
catch(CFileException *e)
{
e->Delete();
return(FALSE);
}

return true;
} ( best_blue 发表于 2006-6-8 15:20:00)
 
调试是没有错误!!但是要知道这个程序的目的就是将DIB保存到bmp文件中! 而这个程序保存后根本就是空白文件!!!也就是这个程序还没有取到内存中的数据 望各位老兄指点  为什么  会这样  要怎么样才能将自己的数据保存到bmp文件中 ( t_ch_w 发表于 2006-4-3 8:43:00)
 
楼主程序很好,基本没有错误!
*((char *)&bmfh.bfType) = ''B'';
*(((char *)&bmfh.bfType) + 1) = ''M'';
把 B M 的双引号改成单引号就可以了 ( edove_Sun 发表于 2005-10-8 21:54:00)
 
保存位图调用gdi+方便多了,还可以保存为JPG,GIF,PNG,TIFF等格式

( 鬼龙之舞 发表于 2005-8-24 9:35:00)
 
楼主,你试过自己的程序没有啊?你的程序保存之后的文件大小为0,而且打不开,你看看是不是有地方错了 ( kongting1981 发表于 2005-8-17 14:06:00)
 
很好 ( rose8391 发表于 2005-4-25 21:02:00)
 
.......................................................

--------------------next---------------------

阅读(176) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~