程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 使VC顯示jpg gif圖像

使VC顯示jpg gif圖像

編輯:vc教程

一、 引言

  JPEG圖像壓縮標准隨然是一種有損圖像壓縮標准,但由於人眼視覺的不敏感,經壓縮後的畫質基本沒有發生變化,很快便以較高的壓縮率得到了廣泛的認可。GIF格式雖然僅支持256色但它對於顏色較少的圖像有著很高的壓縮率,甚至超過JPEG標准,也得到了廣泛的認同。但作為眾多程序員的一個重要的開發工具--Microsoft Visual C++ 6.0的MFC庫卻僅對沒有經過任何壓縮的BMP位圖文件有著良好的支持,可以讀取、顯示、存儲甚至在內存中創建一塊內存位圖。由於BMP格式的圖像沒有經過任何的壓縮,不論是作為程序的外部文件,還是作為程序的內部資源都要占據大量的空間,尤其是後者會大大增加可執行文件的長度。可以看出,如果能用經過壓縮、具有較好的壓縮率的JPEG或GIF格式的圖像來取代BMP文件在VC中的應用,無疑還是很有吸引力的。

  二、 設計思路

  雖然有一些操作、處理JPEG、GIF等其他格式圖像的Active X控件,但總的來說使用起來並不太方便,筆者經過實驗摸索,總結出了一種借助於COM接口的OLE方法來實現上述功能的一種簡便方法,現介紹如下以飨廣大讀者:

  下面我們要使用IPicture 的COM接口,有必要對該圖像接口做些了解:該接口主要管理圖像對象及其屬性,圖像對象為 位圖、圖標和圖元等提供一種與語言無關的抽象。和標准的字體對象一樣,系統也提供了對圖像對象的標准實現。其主要的接口是IPicture和IPictureDisp,後者是由IDispatch接口派生以便通過自動化對圖像的屬性進行訪問。圖像對象也支持外部接口IPropertyNotifySink,以便用戶能在圖像屬性發生改變時作出決定。圖像對象也支持IPersistStream接口,所以它能從一個IStream接口的實例對象保存、裝載自己,而IStream接口也支持對流對象的數據讀寫。

  我們可以用函數OleLoadPicture從包含有圖像數據的流中裝載圖像。該函數簡化了基於流的圖像對象的創建過程,可以創建一個新的圖像對象並且用流中的內容對它進行初始化。其函數原型為:

  STDAPI OleLoadPicture( IStream * pStream, //指向包含有圖像數據的流的指針

  LONG lSize, //從流中讀取的字節數

  BOOL fRunmode, //圖像屬性對應的初值

  REFIID riid, //涉及到的接口標識,描述要返回的接口指針的類型

  VOID ppvObj // 在rrid中用到的接口指針變量的地址) ;

三、 具體的實現

  在顯示圖像之前,首先要獲取到圖像文件的存放路徑,這裡采用標准的文件打開對話框來選取圖像文件,文件名存放在CString 型的變量m_sPath中:   

  CFileDialog dlg(TRUE,"jpg","*.jpg",

  OFN_HIDEREADONLY OFN_OVERWRITEPROMPT,

  "JPEG文件(*.jpg) *.jpg GIF文件(*.gif) *.gif  ",NULL);

  if(dlg.DoModal()==IDOK)

  {

   m_sPath=dlg.GetPathName();

   Invalidate();

  }

  為簡單計,圖形顯示的代碼直接在視類中的OnDraw中編寫,首先打開文件並判斷文件的可用性,並把文件內容放到流接口IStream的對象pStm中:   

  IStream *pStm;

  CFileStatus fstatus;

  CFile file;

  LONG cb;

  ……

  if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1))

  {

   HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);

   LPVOID pvData = NULL;

   if (hGlobal != NULL)

   {

    if ((pvData = GlobalLock(hGlobal)) != NULL)

    {

     file.ReadHuge(pvData, cb);

     GlobalUnlock(hGlobal);

     CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);

    }

   }

  }

 然後,就直接調用OleLoadPicture函數從流中裝載圖像:   

  IPicture *pPic;

  ……

  OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic));

  由於該函數有時會導致失敗,所以應當用SUCCEEDED宏來做一些適當的保護工作,只有在數據裝載成功的前提下才能繼續下面的圖像顯示工作:   

  if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))

  {

   OLE_XSIZE_HIMETRIC hmWidth;

   OLE_YSIZE_HIMETRIC hmHeight;

   pPic->get_Width(&hmWidth);

   pPic->get_Height(&hmHeight);

   double fX,fY;

   ……

   fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);

   fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);

   if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWord)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) {

    AfxMessageBox("渲染圖像失敗!");

    pPic->Release();

   }

   else

   AfxMessageBox("從流中裝載圖像失敗!");

  }

 其中,顯示工作主要是由IPicture接口對象的Render函數來完成的,該函數主要用來將圖片的指定部分畫到指定的設備環境的指定位置。原型如下:   

  HRESULT Render( HDC hdc, //渲染圖像用的設備環境句柄

  long x, //在hdc上的水平坐標

  long y, //在hdc上的垂直坐標

  long cx, //圖像寬度

  long cy, //圖像高度

  OLE_XPOS_HIMETRIC xSrc, //在源圖像上的水平偏移

  OLE_YPOS_HIMETRIC ySrc, //在源圖像上的垂直偏移

  OLE_XSIZE_HIMETR

[1] [2] 下一頁

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved