vc gdi+缩放图片

VC下显示JPG,BMP,GIF等图像格式(转载)

方法一:用COM组件的 IPicture接口(VC)

方法二:用GDI+(VC)

EVC下显示图片

用COM组件的 IPicture接口(VC)

在OnPaint   或 OnDraw中加入下代码即可 (注意 屏蔽掉 CXXDialog::OnPaint CXX::OnDraw)

dc.SetBkMode( TRANSPARENT );

CFile mFile; 
LONG nLength;

//1 打开文件并获得文件的真实大小
if ( mFile.Open( _T( "./res/test.jpg" ),CFile::modeRead )
   &&( ( nLength = mFile.GetLength() ) > 0 ) ) 

   //2 从堆中分配指定数量字节的一整块,这时系统无法提供零零碎碎的局部或全局的堆
   HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nLength ); 
   LPVOID pvData = NULL; 
   if ( hGlobal != NULL ) 
   { 
    //3 锁定全局内存对象并返回它的首地址
    if ( ( pvData = GlobalLock(hGlobal) ) != NULL ) 
    { 
     //4 把文件内容读进全局内存对象的地址空间中
     mFile.Read( pvData, nLength );
     mFile.Close();

     //5 GlobalUnlock函数把以GMEM_MOVEABLE方式分配的内存对象的锁定计数器减1
     GlobalUnlock( hGlobal );

     //6 从全局内存中创建stream对象,第二个参数指定当stream释放时是否自动释放全局内存
     IStream *pStm;
     CreateStreamOnHGlobal( hGlobal, TRUE, &pStm) ;

     //7 创建一个新的picture对象并用stream对象中的内容初始化
     IPicture *pPic; 
     if( SUCCEEDED( OleLoadPicture( pStm, nLength, TRUE, IID_IPicture, (LPVOID*)&pPic ) ) ) 
     { 
      //8 释放不要的stream对象并清空stream指针
      pStm->Release();
      pStm=NULL;
     
      OLE_XSIZE_HIMETRIC mWidth; 
      OLE_YSIZE_HIMETRIC mHeight;

      //9 得到picture对象中图片的宽和高
      pPic->get_Width( &mWidth ); 
      pPic->get_Height( &mHeight );

      CRect rc;
      GetClientRect( &rc );
      double fX,fY;

      //10 GetDeviceCaps(HORZRES)得到屏幕的宽度(单位:像素)
      //    GetDeviceCaps(HORZSIZE)得到屏幕的宽度(单位:毫米)
      fX = (double) dc.GetDeviceCaps(HORZRES) * (double)mWidth / ( (double)dc.GetDeviceCaps( HORZSIZE ) * 100.0 ); 
      fY = (double) dc.GetDeviceCaps(VERTRES) * (double)mHeight / ( (double)dc.GetDeviceCaps( VERTSIZE ) *100.0 );

     
      
      //11 把图像显示在dc中

      if( FAILED( pPic->Render( dc.GetSafeHdc(), 0, 0, (DWORD)fX , (DWORD)fY , 0, mHeight, mWidth, -mHeight, NULL ) ) ) 
       AfxMessageBox( _T("渲染图片失败") );

      /*根据背景大小缩放图片
      CRect rcClient;
      GetClientRect( &rcClient );
      
      BOOL bWidth = rcClient.Width() / fX > rcClient.Height() / fY;
      if ( bWidth )
      {
       if( FAILED( pPic->Render( dc.GetSafeHdc(), 0, 0, (DWORD)rcClient.Width() , (DWORD)rcClient.Width() * fY / fX , 0, mHeight, mWidth, -mHeight, NULL ) ) ) 
        AfxMessageBox( _T("渲染图片失败") );
      }
      else
      {
       if( FAILED( pPic->Render( dc.GetSafeHdc(), 0, 0, (DWORD)rcClient.Height() * fX/ fY, (DWORD)rcClient.Height() , 0, mHeight, mWidth, -mHeight, NULL ) ) ) 
        AfxMessageBox( _T("渲染图片失败") );
      }
      */
      
      //12 释放不要的picture对象,并把指针清空
      pPic->Release(); 
      pPic=NULL;

      //13 释放不要的全局内存对象,这个千万别忘了(32位程序不需要这行,系统会自动释放;16位程序一定要)
      FreeResource(hGlobal);

     }
     else
      AfxMessageBox( _T("从stream中装载图片失败") );

    } 
   }
   else
    AfxMessageBox( _T("分配内存失败") );

else
   AfxMessageBox( _T("打开文件失败") );

用GDI+(VC)

添加Gdiplus.lib到工程中

头文件中添加

#include "Gdiplus.h" 
using namespace Gdiplus;


添加类成员变量

GdiplusStartupInput m_gdiPlusInPut;
ULONG_PTR m_gdiPlusToken;

构造函数中初始化GDI+

GdiplusStartup( &m_gdiPlusToken, &m_gdiPlusInPut, NULL );


析构函数中 //销毁GDI+

GdiplusShutdown(gdiplusToken);

OnPaint()中

//CDialog::OnPaint();
CPaintDC dc( this );

//建立图形对象 
Graphics mGraphics( dc.GetSafeHdc() );

//装入图像文件

Image img( L"./res/test.jpg", TRUE );

//在指定区域pdestPoints显示图像

/*//根据背景大小按比例缩放

CRect rcClient;
GetClientRect( &rcClient );


BOOL bWidth = rcClient.Width() / img.GetWidth() > rcClient.Height() / img.GetHeight();
if ( bWidth )
{
   mGraphics.DrawImage( &img, 0, 0, rcClient.Width(), rcClient.Width() * img.GetHeight() / img.GetWidth() );
}
else
{
   mGraphics.DrawImage(&img, 0, 0, rcClient.Height() * img.GetWidth() / img.GetHeight(), rcClient.Height() );
}

//原始大小
mGraphics.DrawImage(&img, 0, 0, img.GetWidth(), img.GetHeight() );

EVC下显示图片:

void CXXDlg::OnPaint() 
{
CPaintDC dc(this); // device context for painting

dc.SetBkMode( TRANSPARENT );
CBitmap mBitmap;
mBitmap.Attach( SHLoadImageFile( _T( "./player.jpg" ) ) );

BITMAP mInfo;
mBitmap.GetBitmap( &mInfo );

CDC mPicDC;
mPicDC.CreateCompatibleDC( &dc );
CBitmap* pOldBitmap = mPicDC.SelectObject( &mBitmap );
dc.BitBlt( 0, 0, mInfo.bmWidth, mInfo.bmHeight, &mPicDC, 0, 0, SRCCOPY );

mPicDC.SelectObject( pOldBitmap );
mBitmap.DeleteObject();
}




Image::GetThumbnailImage(但是MSDN中提到:如果图片文件有内嵌的缩略图,那么就提取这个缩略图返回,否则才会缩放原图片) 


或者下面的方法(只适合24位色深的格式) 
Bitmap   *   ScaleBitmap(Bitmap   *   pBitmap,UINT   nWidth,UINT   nHeight) 



Bitmap   *   pTemp   =   new   Bitmap(nWidth,nHeight,pBitmap-> GetPixelFormat()); 

if(   pTemp   ) 



Graphics   *   g   =   Graphics::FromImage(pTemp); 

if(   g   ) 



//   use   the   best   interpolation   mode   

g-> SetInterpolationMode(InterpolationModeHighQualityBicubic); 

g-> DrawImage(pBitmap,0,0,nWidth,nHeight); 

delete   g; 





return   pTemp; 




从最新的Platform   SDK中就可以找到了


如果你用GDI处理的话,就在内存中把JPG转为BMP格式然后再缩放显示,不过JPG转BMP的代码非常复杂,光转换的原理就可以整整写一本书了。
如果用GDI+处理的话,就简单了,windows常用图片格式GDI+都是用同样的方式处理的,可以不去考虑图片的格式

bitmap1,bitmap2,bitmap3        //你要显示的图片用Bitmap bitmap1(L"jpg图片绝对路径");来构造
rect1,rect2,rect3                  //图片要缩放到的区域是Rect,而不是Crect
x2,y2,x3,y3                           //第二,三张图片要显示的起始位置

Graphics graphics(this->GetDC()->m_hDC);
graphics.DrawImage(&bitmap1,rect1,0,0,bitmap1.GetWidth(),bitmap1.GetHeight(),UnitPixel);
graphics.TranslateTransform(x2,y2);
graphics.DrawImage(&bitmap2,rect2,0,0,bitmap2.GetWidth(),bitmap2.GetHeight(),UnitPixel);
graphics.TranslateTransform(x3,y3);
graphics.DrawImage(&bitmap3,rect3,0,0,bitmap3.GetWidth(),bitmap3.GetHeight(),UnitPixel);

VC中如何等比例缩放图像

在放大或缩小图像时,如何能最好的保持图像原态比例来显示呢?下面提供一个涵数可帮你来实现,调用它后,返回的矩形区域既为最佳显示图像大小。

  涵数中的第一个参数rcScreen为图像要被显示的矩形大小,第二个参数sizePicture为图像自身大小,第三个参数bCenter为是否居中显示,返回值CRect既为图像最佳显示大小。

  涵数如下所示:

  CRect RectSizeWithConstantRatio( CRect* rcScreen,

  CSize sizePicture,

  BOOL bCenter)

  {

  CRect rect(rcScreen);

  double dWidth = rcScreen->Width();

  double dHeight = rcScreen->Height();

  double dAspectRatio = dWidth/dHeight;

  double dPictureWidth = sizePicture.cx;

  double dPictureHeight = sizePicture.cy;

  double dPictureAspectRatio = dPictureWidth/dPictureHeight;

  //If the aspect ratios are the same then the screen rectangle

  // will do, otherwise we need to calculate the new rectangle

  if (dPictureAspectRatio > dAspectRatio)

  {

  int nNewHeight = (int)(dWidth/dPictureWidth*dPictureHeight);

  int nCenteringFactor = (rcScreen->Height() - nNewHeight) / 2;

  rect.SetRect( 0,

  nCenteringFactor,

  (int)dWidth,

  nNewHeight + nCenteringFactor);

  }

  else if (dPictureAspectRatio < dAspectRatio)

  {

  int nNewWidth = (int)(dHeight/dPictureHeight*dPictureWidth);

  int nCenteringFactor = (rcScreen->Width() - nNewWidth) / 2;

  rect.SetRect( nCenteringFactor,

  0,

  nNewWidth + nCenteringFactor,

  (int)(dHeight));

  }

  return rect;

  };

  l 此涵数的使用方法如下:

  {

  ……(部分省略)

  //得到屏幕大小

  CRect rcScreen( 0, 0,

  GetSystemMetrics(SM_CXSCREEN),

  GetSystemMetrics(SM_CYSCREEN));

  //得到图像尺寸

  CSize sizePicture(picture.m_Width, picture.m_Height);

  CRect rcNewPictureRect =

  SizeRectWithConstantAspectRatio(&rcScreen,

  sizePicture,

  TRUE);

  picture.Show(&dc, rcNewPictureRect);

  }



  1. #include <ocidl.h>   
  2. #include <olectl.h> 
  3.  
  4. // lpstrFile:文件名(最好是包含路径在内)   
  5. // hWnd   
  6. // nScrWidth:输出图片的宽度   
  7. // nScrHeight:输出图片的高度   
  8. // nScrWidth、nScrHeight是输出图片的实际大小,换而言之是指缩放后的尺寸  
  9.  
  10. HRESULT ShowPic(char *lpstrFile,HWND hWnd,int nScrWidth,int nScrHeight)   
  11. {   
  12. HDC hDC_Temp=GetDC(hWnd);  
  13.  
  14. IPicture *pPic;   
  15. IStream *pStm;  
  16.  
  17. BOOL bResult;  
  18.  
  19. HANDLE hFile=NULL;   
  20. DWORD dwFileSize,dwByteRead;  
  21.  
  22. //打开硬盘中的图形文件   
  23. hFile=CreateFile(lpstrFile,GENERIC_READ,   
  24. FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);  
  25.  
  26. if (hFile!=INVALID_HANDLE_value)   
  27. {   
  28. dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数  
  29.  
  30. if (dwFileSize==0xFFFFFFFF)   
  31. return E_FAIL;   
  32. }   
  33. else   
  34. {   
  35. return E_FAIL;   
  36. }  
  37.  
  38.  
  39. //分配全局存储空间   
  40. HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);   
  41. LPVOID pvData = NULL;  
  42.  
  43. if (hGlobal == NULL)   
  44. return E_FAIL;  
  45.  
  46. if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块   
  47. return E_FAIL;  
  48.  
  49. ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区  
  50.  
  51. GlobalUnlock(hGlobal);  
  52.  
  53. CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);  
  54.  
  55. //装入图形文件   
  56. bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic);  
  57.  
  58. if(FAILED(bResult))   
  59. return E_FAIL;  
  60.  
  61. OLE_XSIZE_HIMETRIC hmWidth;//图片的真实宽度   
  62. OLE_YSIZE_HIMETRIC hmHeight;//图片的真实高度   
  63. pPic->get_Width(&hmWidth);   
  64. pPic->get_Height(&hmHeight);  
  65.  
  66.  
  67. //将图形输出到屏幕上(有点像BitBlt)   
  68. bResult=pPic->Render(hDC_Temp,0,0,nScrWidth,nScrHeight,   
  69. 0,hmHeight,hmWidth,-hmHeight,NULL);  
  70.  
  71. pPic->Release();  
  72.  
  73. CloseHandle(hFile);//关闭打开的文件  
  74.  
  75. if (SUCCEEDED(bResult))   
  76. {   
  77. return S_OK;   
  78. }   
  79. else   
  80. {   
  81. return E_FAIL;   
  82. }   
  83. }  
我找到一个解决的方法啦:通过位图来转换 
  //wRatio   hRatio分别为Width和Height调整的百分比(%) 
int     ResizePicture(LPCWSTR   lpSrcFile,LPCWSTR   lpDstFile,int   wRatio,int   hRatio)         

Image     srcImg(lpSrcFile); 
int   srcWidth=srcImg.GetWidth(); 
int   srcHeight=srcImg.GetHeight(); 
                  //计算调整后的Width和Height 
int   dstWidth=srcWidth*wRatio/100; 
int   dstHeight=srcHeight*hRatio/100; 
//   Construct   a   Graphics   object   based   on   the   image. 
Graphics   imgGraphics(&srcImg); 

Bitmap   bitmap(dstWidth,dstHeight,&imgGraphics); 
Graphics   bmpGraphics(&bitmap); 
bmpGraphics.DrawImage(&srcImg,0,0,dstWidth,dstHeight); 
//   Save   the   altered   image. 
LPWSTR   lpExt=PathFindExtensionW(lpSrcFile); 
lpExt++; 
LPWSTR   lpEncoder; 
switch(*lpExt) 

case   L 'J ': 
case   L 'j ': 
lpEncoder=L "image/jpeg "; 
break; 
case   L 'P ': 
case   L 'p ': 
lpEncoder=L "image/png "; 
break; 
case   L 'B ': 
case   L 'b ': 
lpEncoder=L "image/bmp "; 
break; 
case   L 'G ': 
case   L 'g ': 
lpEncoder=L "image/gif "; 
break; 
case   L 't ': 
case   L 'T ': 
lpEncoder=L "image/tiff "; 
break; 
default: 
lpEncoder=L "image/jpeg "; 


CLSID   imgClsid; 
                  //GetEncoderClsid()函数是在MSDN中的例子 
GetEncoderClsid(lpEncoder,   &imgClsid); 
bitmap.Save(lpDstFile,&imgClsid,NULL); 

return   0; 
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值