1、保存为BMP图片格式
//将内存绘制的图保存为 HBITMAP,调用时可以按照尺寸只截取整个绘图区域的一部分
HBITMAP CopyDCToBitmap(HDC hScrDC, LPRECT lpRect)
{
HDC hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 位图宽度和高度
// 确保选定区域不为空矩形
if ( IsRectEmpty( lpRect ) ) return NULL;
// 获得选定区域坐标
nX= lpRect->left;
nY= lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC= CreateCompatibleDC( hScrDC );
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap( hScrDC, nWidth, nHeight );
// 把新位图选到内存设备描述表中
hOldBitmap = ( HBITMAP )SelectObject( hMemDC, hBitmap );
// 把屏幕设备描述表拷贝到内存设备描述表中
StretchBlt( hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, nWidth, nHeight, SRCCOPY );
//得到屏幕位图的句柄
hBitmap = ( HBITMAP )SelectObject( hMemDC, hOldBitmap );
//清除
DeleteDC( hMemDC );
DeleteObject( hOldBitmap );
//返回位图句柄
return hBitmap;
}
//保存到BMP文件
BOOL SaveBmp(HBITMAP hBitmap, CString FileName)
{
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject( hBitmap, sizeof( Bitmap ), ( LPSTR )&Bitmap );
bi.biSize = sizeof( BITMAPINFOHEADER );
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
//hDC = m_pDc->GetSafeHdc();
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
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; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
/以上函数转载///
//应用程序函数,调用上面的2个函数
void OnSavebmp()
{
//----------------------------------------------------
// 经过这一句:MenDC.SelectObject(&bm);以后,不管使用
// MenDC绘制什么,实际上都是绘制在了CBitmap bm;这个内
// 存位图上了.
//----------------------------------------------------
CFileDialog dlg(FALSE,L"*.BMP",NULL,NULL,L"BMP文件(*.BMP)|*.BMP||");
if (dlg.DoModal()==IDOK)
{
CString strFileName = dlg.GetPathName();//获得文件名及路径(包含后缀)
CDC *pdc=GetDC();// 下面是创建兼容DC和兼容DC使用的CBitmap,并规定兼容DC的绘图绘制在创建的CBitmap上。
CDC MenDC; //内存绘图设备
CBitmap bm; //定义一个位图对象
CRect mRect(0,0,1800,2500);//定义绘图的矩形区域大小,根据实际需要设置
MenDC.CreateCompatibleDC( NULL ); //创建内存绘图设备
bm.CreateCompatibleBitmap( pdc, mRect.Width(), mRect.Height() ); //设定背景位图大小,最好是整个客户区大小
MenDC.SelectObject( &bm );
//----------------------------------------------------
// 下面使用MenDC绘制你想要的任何东西
//----------------------------------------------------
MenDC.Ellipse(100,100,500,500);//绘制圆
HBITMAP hBmp = CopyDCToBitmap(MenDC.GetSafeHdc(), &mRect ); //mRect可以根据需要截取部分图片
SaveBmp(hBmp, strFileName);//保存为BMP文件
bm.DeleteObject();
MenDC.DeleteDC();
ReleaseDC(pdc);
}
}
2.保存为JEPG(jpg)图片格式
思路:先保存为bmp格式,再将其转化为JEPG
//=======================================================================
// 函数原型: BOOL CSYSGlobal::BMP2JPEG(LPCTSTR lpszBMPFileName, LPCTSTR lpszJPEGFileName , long lQuality /*= 100*/ )
// 功能描述: BMP文件转换成JPEG文件
// 参数说明: 名称 类型 说明
// lpszBMPFileName LPCTSTR 要转换的BMP文件名( 已存在文件 )
// lpszJPEGFileName LPCTSTR JPEG文件名( 根据BMP转换 新生成文件 )
// lQuality long 图片质量 ( 默认100% )
// 返 回 值:
// 依 赖 于: GDI+, ATL字符转换( 用 A2W() 转换ASCII -> Unicode )
// 具体 做法如下:
// 1. 加入GDI+支持: 在StdAfx.h的 "#endif // _AFX_NO_AFXCMN_SUPPORT" 前加入如下代码:
// #include <gdiplus.h>
// #include <GdiPlusEnums.h>
// using namespace Gdiplus;
// #pragma comment( lib, "gdiplus.lib" )
//
// //加入ATL字符转换支持: 在StdAfx.h中加入
// #include <atlconv.h>
//-----------------------------------------------------------------------
// 引 用 表: 无
// 更 新 表: 无
// 被引用于: 全局
// 创建日期: 2007年12月21日 16时02分57秒
// 修改日期:
// 修改说明:
//=======================================================================
BOOL CTypeValidate::BMP2JPEG(LPCTSTR lpszBMPFileName, LPCTSTR lpszJPEGFileName, long lQuality /*= 100*/ )
{
USES_CONVERSION; //调用 A2W() 等宏时,必须先执行该行!!!
CLSID codecClsid;
EncoderParameters encoderParameters;
long quality;
Status stat;
GdiplusStartupInput gdiplusStartupInput;
ULONG gdiplusToken;
BOOL bRet = TRUE;
WCHAR wszcBmpFileName[ 512 ];
WCHAR wszJpgFileName[ 512 ];
WCHAR *lpwcBmpFileName = NULL;
WCHAR *lpwcJpgFileName = NULL;
#ifdef UNICODE
wcscpy_s( wszcBmpFileName, lpszBMPFileName );
wcscpy_s( wszJpgFileName, lpszJPEGFileName );
#else
lpwcBmpFileName = A2W( lpszBMPFileName );
lpwcJpgFileName = A2W( lpszJPEGFileName );
wcscpy( wszcBmpFileName, lpwcBmpFileName );
wcscpy( wszJpgFileName, lpwcJpgFileName );
#endif
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
{
// Get an image from the disk.
Image image( wszcBmpFileName );
// Get the CLSID of the JPEG codec.
GetCodecClsid( L"image/jpeg", &codecClsid );
// Before we call Image::Save, we must initialize an
// EncoderParameters object. The EncoderParameters object
// has an array of EncoderParameter objects. In this
// case, there is only one EncoderParameter object in the array.
// The one EncoderParameter object has an array of values.
// In this case, there is only one value ( of type LONG )
// in the array. We will set this value to 0, 50, and 100.
encoderParameters.Count = 1;
encoderParameters.Parameter[0].Guid = EncoderQuality;
encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParameters.Parameter[0].NumberOfValues = 1;
// Save the image as a JPEG with quality level 0.
quality = lQuality;
encoderParameters.Parameter[0].Value = &quality;
stat = image.Save( wszJpgFileName, &codecClsid, &encoderParameters);
if( stat == Ok )
{
//AfxMessageBox( _T( "保存JPEG文件成功" ) );
bRet = TRUE;
}
else
{
AfxMessageBox( _T( "保存JPEG文件失败!" ) );
bRet = FALSE;
}
}
GdiplusShutdown(gdiplusToken);
return bRet;
}
//=======================================================================
// 函数原型: int GetCodecClsid(const WCHAR *format, CLSID *pClsid)
// 功能描述:
// 参数说明: 名称 类型 说明
// 返 回 值:
// 依 赖 于: 无
// 引 用 表: 无
// 更 新 表: 无
// 被引用于: BOOL CSYSGlobal::BMP2JPEG(LPCTSTR lpszBMPFileName, LPCTSTR lpszJPEGFileName )
// 创建日期: 2007年12月21日 16时43分28秒
// 修改日期:
// 修改说明:
//=======================================================================
int CTypeValidate::GetCodecClsid(const WCHAR *format, CLSID *pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
{
return -1; // Failure
}
pImageCodecInfo = (ImageCodecInfo*)( malloc( size ) );
if(pImageCodecInfo == NULL)
{
return -1; // Failure
}
GetImageEncoders(num, size, pImageCodecInfo);
for( int j = 0; j < (int)num; ++j )
{
if( wcscmp(pImageCodecInfo[j].MimeType, format ) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
return j; // Success
}
} // for
return -1; // Failure
}
///以上函数转载/
************************************************************************************************//
函数名称: OnSavejepg
函数类型: void
返 回 值: null
功能描述: 保存为jepg文件
函数作者:
创建日期:
参数列表:
变量名: 变量类型: 变量说明:
************************************************************************************************//
void CLeftView::OnSavejepg()
{
//----------------------------------------------------
// 经过这一句:MenDC.SelectObject(&bm);以后,不管使用
// MenDC绘制什么,实际上都是绘制在了CBitmap bm;这个内
// 存位图上了.
//----------------------------------------------------
//CFileDialog dlg(FALSE,L"*.jpg",NULL,NULL,L"JEPG文件(*.JEPG)|*.JEPG|jpg文件(*.jpg)|*.jpg||");
CFileDialog dlg(FALSE,L"*.jpg",NULL,NULL,L"jpg文件(*.jpg)|*.jpg||");
if (dlg.DoModal()==IDOK)
{
CString strFileName = dlg.GetPathName();//获得文件名及路径(包含后缀)
strFileName = strFileName.Left(strFileName.GetLength()-4);//获得文件名及路径(不包含后缀)
CDC *pdc=GetDC();// 下面是创建兼容DC和兼容DC使用的CBitmap,并规定兼容DC的绘图绘制在创建的CBitmap上。
CDC MenDC; //内存绘图设备
CBitmap bm; //定义一个位图对象
CRect mRect(0,0,1800,2500);
MenDC.CreateCompatibleDC( NULL ); //创建内存绘图设备
bm.CreateCompatibleBitmap( pdc, mRect.Width(), mRect.Height() ); //设定背景位图大小,最好是整个客户区大小
MenDC.SelectObject( &bm );
MenDC.FillSolidRect(mRect, WhiteColor);
//----------------------------------------------------
// 下面使用MenDC绘制你想要的任何东西
//----------------------------------------------------
MenDC.Ellipse(100,100,500,500);//绘制圆
CString strName, strJEPG;
strName.Format(L"%s.bmp",strFileName);
HBITMAP hBmp = CopyDCToBitmap(MenDC.GetSafeHdc(), &mRect );
SaveBmp(hBmp, strName);//保存为BMP文件
strJEPG.Format(L"%s.jpg",strFileName);
BMP2JPEG(strName, strJEPG, 100);//转存为jpg
DeleteFile(strName);//删除bmp
MessageBox(L"保存完成");
bm.DeleteObject();
MenDC.DeleteDC();
ReleaseDC(pdc);
}
}