用MFC写了一个图形绘制程序,主要的绘制工作由其中一个类的Draw(CDC* pDC, ...)函数完成。
现在想添加一个将绘制出的图形保存为BMP图像的功能。不知道该怎么实现。
网上查了一些东西,好像要弄明白原理内容还是比较多的。这里就先只完成代码了。
请知道的帮我写一写将绘制好的图形(Draw())保存为BMP图像的代码。
先行谢过了!
现在想添加一个将绘制出的图形保存为BMP图像的功能。不知道该怎么实现。
网上查了一些东西,好像要弄明白原理内容还是比较多的。这里就先只完成代码了。
请知道的帮我写一写将绘制好的图形(Draw())保存为BMP图像的代码。
先行谢过了!
DWORD dwpalettelsize=0;//调色板大小
DWORD dwbmdibitsize,dwdibsize,dwwritten;
BITMAP bitmap;//定义了位图的各种的信息。
BITMAPFILEHEADER bmfhdr;//定义了大小、类型等BMP文件的信息。
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh,fdib;
GetObject(hBitmap,sizeof(BITMAP),(void *)&bitmap);//得到BITMAP结构。
//以下代码是用BITMAP的信息填充BITMAPINFOHEADER结构
wbitsCount=bitmap.bmBitsPixel;
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=bitmap.bmWidth;
bi.biHeight=bitmap.bmHeight;
bi.biPlanes=1;
bi.biBitCount= bitmap.bmBitsPixel ;
bi.biClrImportant=0;
bi.biClrUsed=0;
bi.biCompression=BI_RGB;
bi.biSizeImage=0;
bi.biYPelsPerMeter=0;
bi.biXPelsPerMeter=0;
//以下代码是获取调色板的长度,调色板现在的用处很少,因为256色的位图已经不多了。
if(wbitsCount <=8)
dwpalettelsize=(1 < <wbitsCount)*sizeof(RGBQUAD);
//计算位图的大小,并分配相应的内存空间,注意的是没有分配BITMAPFILEHEADER。
dwbmdibitsize=((bitmap.bmWidth*wbitsCount+31)/8)*bitmap.bmHeight;
fdib=GlobalAlloc(GHND,dwbmdibitsize+dwpalettelsize+sizeof(BITMAPINFOHEADER));
lpbi=(LPBITMAPINFOHEADER)::GlobalLock(fdib);
*lpbi=bi;//将bi中的数据写入分配的内存中。
hdc=::GetDC(NULL);
GetDIBits(hdc,hBitmap,0,(UINT)bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwpalettelsize,(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
/*GetDIBits是最重要的函数,真正获得位图数据的工作就由它完成,它第一个参数为HDC,第二个参数为位图句柄,第三个参数为扫描行的开始行,一般为0,第四个为结束行,一般就是高度,第四个参数最重要,它表示接收数据的起始地址,这个地址一般是在调色板之后。第五个参数指的是接收 BITMAPINFO结构的地址,这个结构上面没有写,它其实就是BITMAPINFO结构加上调色板信息。最后一个参数是格式。一般是 DIB_RGB_COLORS*/
//创建文件以及文件信息头
fh=CreateFile(FileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(fh==INVALID_HANDLE_VALUE)
return FALSE;
bmfhdr.bfType=0x4d42;//BMP类型,一定要这样写
dwdibsize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwbmdibitsize+dwpalettelsize; //文件总长,由几个部分组成
bmfhdr.bfSize=dwdibsize;
bmfhdr.bfReserved1=0;
bmfhdr.bfReserved2=0;
bmfhdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+ (DWORD)sizeof(BITMAPINFOHEADER)+dwpalettelsize;//位图数据相对于文件头的偏移量
//将文件信息头写入文件
WriteFile(fh,(LPSTR)&bmfhdr,sizeof(BITMAPFILEHEADER),&dwwritten,NULL);
//将数据写入文件,包含BITMAPINFO结构、调色板、数据
WriteFile(fh,(LPSTR)lpbi,dwdibsize,&dwwritten,NULL);
//关闭相关句柄
::GlobalUnlock(fdib);
::GlobalFree(fdib);
::CloseHandle(fh);
return TRUE;
HDC hDC = ::GetDC(m_hWnd); RECT rect;
::GetClientRect(m_hWnd, &rect);
HDC hDCMem = ::CreateCompatibleDC(hDC); HBITMAP hBitMap = ::CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
HBITMAP hOldMap = (HBITMAP)::SelectObject(hDCMem, hBitMap); ::BitBlt(hDCMem, 0, 0, rect.right, rect.bottom, hDC, 0, 0, SRCCOPY); CImage image;
image.Attach(hBitMap);
image.Save("c:\\B.bmp");
image.Detach(); ::SelectObject(hDCMem, hOldMap);
::DeleteObject(hBitMap);
::DeleteDC(hDCMem);
::DeleteDC(hDC);
我写的小程序是一个使用滚动条(就是说绘图区域比可见的客户区大),并且要保存的是整个绘图区域的这么一个程序。其中我使用的是GDI的函数,并且是用MM_LWMETRIC的模式。
这样的话,程序应该怎么写呢
SaveAsPicture(CDC* pDC, CString t_FileName, CRect t_BmpRect, CRect t_ClientRect)这是要实现保存图片功能的函数。而具体完成绘制工作的函数是:
void Draw(CDC *pDC, CRect t_ClientRect, CPoint t_Point);
还请你帮我组织一下。
//@brief 获取图片文件的编码方式,支持bmp、jpg、jpeg、gif、tiff和png等格式图片
//@date 1-13-2009
//@param [in] format 图片格式 值可以为以下几种
//@"image/bmp"
//@"image/jpeg"
//@"image/gif"
//@"image/tiff"
//@"image/png"
//@param [in] pClsid
//@return 成功则返回值 >= 0,失败则返回值为-1
int GetEncoderClsid(const WCHAR* format, CLSID *pClsid)
{
int nRet = -1;
ImageCodecInfo* pCodecInfo = NULL;
UINT nNum = 0,nSize = 0;
GetImageEncodersSize(&nNum,&nSize); if (nSize<0)
{
return nRet;
} pCodecInfo= new ImageCodecInfo[nSize]; if (pCodecInfo==NULL)
{
return nRet;
} GetImageEncoders(nNum,nSize,pCodecInfo); for (UINT i=0; i<nNum;i++)
{
if (wcscmp(pCodecInfo[i].MimeType,format)==0)
{
*pClsid= pCodecInfo[i].Clsid;
nRet = i;
delete[] pCodecInfo;
return nRet;
}
else
{
continue;
}
} delete[] pCodecInfo;
return nRet;
}//@brief 用GDI+将Bitmap图片保存为文件
//@date 1-13-2009
//@param [in] hBitmap hBitmap的句柄(handle)
//@param [in] lpszFileName 保存图片的完整路径
//@return 成功返回TRUE,失败返回FALSEBOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
{
CLSID pngClsid; Bitmap bmp(hBitmap,NULL); //获取BMP文件的编码方式(如果希望获取JPEG的编码方式, //那么参数一要设置为:_TEXT("image/jpeg"),其他支持的图片格式类似)
int nResult = GetEncoderClsid(_TEXT("image/bmp"),&pngClsid); if(nResult >= 0)
{
//保存所截取的屏幕图片
bmp.Save(lpszFileName,&pngClsid);
}
else
{
return FALSE;
}
return TRUE;
}