Visual C++多媒體設計及圖形、圖像處理

在VC下顯示JPEG、GIF格式圖像的一種簡便方法一、 引言   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_HIMETRIC cxSrc,//在源圖像上水平拷貝的數量 OLE_YSIZE_HIMETRIC cySrc,//在源圖像上垂直拷貝的數量 LPCRECT prcWBounds //指向目標圖元設備環境句柄的指針);   小結:到此爲止,通過上述代碼已經能夠在程序的客戶區內顯示JPEG、GIF等標準的圖像了,但對於有多幀圖片(即有動畫)的GIF格式的圖像,目前還只能顯示第一幀,如要完整的顯示GIF 動畫的全過程,還需要外部Active X控件的支持。 在屏幕上任何地方畫圖 可以用你的程序在屏幕上的任何地方畫圖,效果就象電子寵物一樣很簡單,只要兩個API The first one is getdesktopwindow and the other is getwindowdc the detail you can see the Win32 help which was plused in Delphi4 For example: you paste a bitmap on the screen var wnd:longint; mydc,bitmapdc:Hdc; mybitmap:Tbitmap; mybitmap:=Tbitmap.create(); mybitmap.loadfromfile(c:\windows\waves.bmp); bitmapdc:=getwindowdc(mybitmap.handle); wnd:=getdesktopwindow(); mydc:=getwindowdc(wnd); bitblt(my....... //I forget the detail if you have any questions can // send email to me at bbs 引入湍流概念實現對大理石紋理的造型模擬 摘要:本文通過在物體表面紋理的造型算法中引入流體力學中的湍流概念而成功實現了對大理石表面紋理的模擬仿真。   前言   計算機仿真模擬技術在生物、醫學以及國防等諸多科研和應用領域得到了廣泛的應用。仿真的過程也就是把仿真對象從物體提煉成數學模型的過程,因此其內在數學模型的提煉和從數學模型設計出相應的仿真算法在整個仿真過程中是很關鍵的兩個環節。本文以大理石爲例,通過引入流體力學中湍流概念從數學角度提出了一個仿真效果比較好的紋理仿真算法,並給出了關鍵部分的VC++編碼。   過程紋理造型技術   過程紋理造型技術在功能同二維紋理管理技術比較相似。但由於二維紋理管理技術採用固定的圖像來描述表面細節,而客觀世界中的自然物體表面紋理卻往往具有較強的不規則性和隨機性,因此這種採用固定圖像對錶面細節進行描述的紋理造型技術效果並不好,不能對自然物體進行較好的造型和模糊。在20世紀80年代中後期提出的過程紋理造型技術採用代碼段或算法來編碼抽取模型細節,並且允許高層控制和規範,從根本上克服了二維紋理管理技術的上述缺陷。而且該技術是通過控制參數來管理紋理數據的放大,因此在仿真過程中只需簡單地設定若干個控制參數就可以動態產生大量豐富的幾何細節。    1985年由Peachey和Perlin所提出的三維紋理映射方法將三維紋理函數直接定義在三維紋理空間中,數學形式爲:   T=T(x,y,z)(T:顏色的RGB值; (x,y,z):空間點三維座標)。現在用來構造三維紋理的基本方法常用的主要有兩種:   基於高頻採樣的數字化紋理和採用數學模型動態計算生成紋理。基於高頻採樣的數字化紋理由於需要有三維數組的支持,在處理高分辨率的紋理時佔用空間將急劇增大,對空間的要求比較苛刻。一些真實感較強的圖形合成系統多采用數學模型動態計算生成紋理的紋理定義方法。經過多年的研究實踐已經開發積累了許多過程迭代函數以產生各種複雜的紋理,這些過程紋理(procedural texture)函數被證明是非常有效的,已經可以對木材、大理石、雲彩、火焰和石板等許多自然物體的紋理進行逼真的模擬仿真。這些函數從本質上來說都是一種經驗模型。   在算法中引入湍流概念   湍流(turbulence)本是流體力學中的重要研究對象,但在此不準備從湍流的精確物理模型出發對其做任何討論,而是提出一種近似描述該物理現象的經驗模型。這種技術最早在1985年由Perlin提出,曾成功用於對大理石、火焰以及雲彩等紋理的仿真。這種經驗模型是由一系列的三維噪聲函數疊加而成,根據流體力學中湍流的有關概念可以得出可以體現上述經驗模型的數學表達式:   turbulence(p)=∑|Noise(pow(2,i)*p)/(pow(2,i))|   其中,p爲一紋理空間中的點(x,y,z)。求和區間爲i從0到k,上限k是滿足下列不等式的最小整數: 1/(pow(2,k+1))<像素通長。通過選取滿足上述條件的求和上限值 k,可以避免採樣湍流函數時的走樣現象。該函數表達式任取和式的相鄰兩項,後一項噪聲函數的變化頻率總是前一項函數的變化頻率的兩倍,幅度則爲前者的一半,也就是對湍流函數的貢獻率減小了一半。因此,上述的構造方法從數學上保證了湍流函數本身就具有一定的自相似特性。從信號分析的角度看,則其功率譜分佈滿足1/f的規律。該函數並不能直接對紋理進行仿真,我們所借鑑的只是其隨機性和自相關特性,這些特性在紋理定義時可以很好的描述各種自然紋理的不規則細節。因此湍流函數在紋理造型算法中還是能起到重要作用的。紋理的描述過程大致分兩步:首先選取一個簡單的合適的函數來描述自然物體如大理石的基本紋理結構特徵,其中選取的這個描述函數一般應當是連續的且其一階導數應具有較大的變化。在選定描述函數後用湍流函數來對描述函數的某些基本參數進行擾動,以產生複雜的不規則紋理細節。   對於本文的研究對象--大理石,可以注意到大理石漂亮的紋理其實是其內部不同組成材質的顏色的反映,因此可以定義一個函數來描述這種構造。大理石區別於普通石材的一個比較明顯的特點是其紋理多呈週期分佈,對此特性可用某方向的正弦波函數作爲彩色濾波:   marble(p) = marble_color(sin(x))   p仍爲空間點(x,y,z),marble_color()爲彩色濾波函數,把[-1,1]區間內任一函數值映射成爲RGB顏色之間的顏色值,通常將其表達爲三條各自獨立的樣條曲線。在採取了紋理描述的第二步引入了湍流擾動後,上述函數變爲最終的描述函數:   marble(p) = marble_color(sin(x+turbulence(p)))   算法的實現   根據前面總結的結論,筆者經過實驗發現,如果定義的樣條曲線在某些點存在較大的一階導數,那麼用該樣條曲線模擬出來的大理石表面紋理將存在較明顯的尖銳邊界。在下面採取的描述算法中樣條曲線爲線性函數(一次樣條),效果還是適中的: COLORREF marble(float px,float py,float pz) { float y=py+3.0*turbulence(px,py,pz,0.0125); y=sin(y*M-PI); return (marble_color(px)); } …… COLORREF marble_color(float px); { COLORREF col; float x=sqrt(px+1.0)*0.7071; int G=(int)(0.30+0.8*x); x=sqrt(x); int R=(int)(0.30+0.6*x); int B=(int)(0.60+0.4*x); return col; } 以上兩段代碼可以較好地對大理石紋理做仿真模擬處理。同其他紋理一樣,湍流函數也可以用來表達各種表面顏色屬性的不規則性如凹凸紋理、透明度等。   小結   本文通過在過程紋理造型技術引入流體力學的湍流概念,成功對大理石的表面紋理作了仿真模擬。通過本文對大理石紋理的計算機仿真的實現過程,可對此類仿真模擬程序有一個基本的認識。湍流函數算法也適用於需要對參數進行擾動處理的其他一些仿真環境。本文程序算法在Windows 98 SE下,由Microsoft Visual C++ 6.0編譯調試通過。 用VC實現桌面文字背景透明擺脫黑白 Module name : Transparent.cpp * * Module description : * To make desktop icon text background transparent. * * Project : * * Target platform : Win32 * * Compiler & Library : Visual C++ 6.0 * * Author : Richard Shen * * Creation date : 19 June, 1999 * #include <windows.h> int main(void) { HWND hWnd; hWnd = GetDesktopWindow(); if ((hWnd = FindWindowEx(hWnd, 0, "Progman", "Program Manager")) == 0) return 1; if ((hWnd = FindWindowEx(hWnd, 0, "SHELLDLL_DefView", NULL)) == 0) return 1; if ((hWnd = FindWindowEx(hWnd, 0, "SysListView32", NULL)) == 0) return 1; // Change icon text attributes SendMessage(hWnd, 0x1026, 0, 0xffffffff); // Turn background to transparent SendMessage(hWnd, 0x1024, 0, 0x00ffffff); // Turn foregound to white InvalidateRect(hWnd, NULL, TRUE); // Repaint return 0; } // main() 用漸變色填充背景 Windows的圖形界面爲我們提供了無窮的方便和視覺上的快感,由淺及深的顏色給我們無盡的遐想。漸變色的實現有多種方法,好多資料上介紹了利用調色板的方法實現,其過程及其的複雜,需要我們具有一定的圖形編程的基礎,下面我將向大家介紹一種比較簡單的方法,即使你一點都不瞭解圖形編程和調色板的概念。   第一步:新建單文檔工程,一切參數都取默認值。   第二步:在shadowview.h中定義變量如下: private: int ColorR; int ColorG;   第三步:在shadowview.cpp的構造函數中初始化變量如下: CShadowView::CShadowView() {  // TODO: add construction code here  ColorR = 255;  ColorG = 255; }   第四步:在Ondraw()中添加如下的實現代碼: void CShadowView::OnDraw(CDC* pDC) {  CShadowDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  // TODO: add draw code for native data here  CRect m_rcClient;  file://得到客戶區域的填充矩形 GetClientRect(&m_rcClient);  int nWidth = m_rcClient.Width();  int nHeight = m_rcClient.Height();  CRect rectangle;  file://分割客戶區域成小矩形,逐個填充  for(int i = 0;i < nWidth;i++ )  {   rectangle.SetRect(i, 0, i+1, nHeight);   pDC->FillSolidRect(&rectangle, RGB(ColorR, ColorG, 255-MulDiv(i, 255, nWidth)));   } }   現在編譯、運行程序,我們可以發現單文檔界面的背景已經被黃漸變色填充。接下來,我們實現在界面上點擊鼠標左鍵,實現背景顏色的改變。   第五步:在ClassWizard中添加鼠標左鍵的消息處理映射函數,並添加如下代碼: void CShadowView::OnLButtonDown(UINT nFlags, CPoint point) {  file://生成小於255的隨機數,給ColorR和ColorG賦值 int nRand = rand();  float fMap = (float)255/RAND_MAX;  ColorR = (UINT)(float)nRand*fMap + 0.5f;  nRand = rand();  fMap = (float)255/RAND_MAX;  ColorG = (UINT)(float)nRand*fMap + 0.5f;  file://更新界面 Invalidate();  CView::OnLButtonDown(nFlags, point); }   好了,所有的功能都實現了,在界面上點擊鼠標左鍵,我們可以發現,背景以不同的漸變色填充。 本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/hln24477932/archive/2007/08/28/1762134.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章