在内存绘图并保存为图片格式

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);
 }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值