亂彈運用Direct技術進行影像裁減的實現(下)(轉)

post0發表於2007-08-12
亂彈運用Direct技術進行影像裁減的實現(下)(轉)[@more@]

  ok,然後就是設定顯示模式的函式,它的原型是:

  HRESULT SetDisplayMode(

  DWORD dwWidth,

  DWORD dwHeight,

  DWORD dwBPP,

  DWORD dwRefreshRate,

  DWORD dwFlags

  );

  

  dwWidth and dwHeight用來設定顯示模式的寬度和高度。

  dwBPP用來設定顯示模式的顏色位數。

  dwRefreshRate設定螢幕的重新整理率,0為使用預設值。

  dwFlags現在唯一有效的值是DDSDM_STANDARDVGAMODE。

  

  建立頁面,先清空,申請空間(類似於c中的解構函式)

  

  memset(&ddsd, 0, sizeof(DDSURFACEDESC2));//開始建立主頁面,先清空頁面描述

  ddsd.dwSize = sizeof( ddsd );//填充頁面描述

  ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; //有後臺快取

  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;

  ddsd.dwBackBufferCount = 1; //一個後臺快取

  lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); //建立主頁面

  

  建立主頁面的函式原型是:

  

  HRESULT CreateSurface(

  LPDDSURFACEDESC2 lpDDSurfaceDesc,

  LPDIRECTDRAWSURFACE FAR *lplpDDSurface,

  IUnknown FAR *pUnkOuter

  );

  

  第一個引數是被填充了頁面資訊的DDSURFACEDESC2結構的地址,此處為&ddsd;

  第二個引數是接收主頁面指標的地址,此處為&lpDDSPrimary;

  第三個引數現在必須為NULL,為該函式所保留。

  

  後面建立放背景和滑鼠的頁面也是一個道理。

  後面就是貼圖,把要顯示的圖片先貼出來,給一個指標指定其位置,後面要使用的的時候直接操作指標即可。不過在這之前還是要清空頁面,最後貼好圖後要設定圖片的透明色,這樣圖片我們才可見。

  

  //清空各個頁面

  DDBLTFX ddBltFx;

  ddBltFx.dwSize=sizeof(DDBLTFX);

  ddBltFx.dwFillColor=0;

  lpDDSPrimary ->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);

  lpDDSBuffer->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);

  lpDDSMap->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);

  lpDDSMouse->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx);

  

  //貼圖和設定透明色

  DDReLoadBitmap(lpDDSMap,"inn.BMP");

  DDReLoadBitmap(lpDDSMouse,"mouse.BMP");

  MakeRect(0,0,640,480);

  lpDDSPrimary->BltFast(0,0,lpDDSMap,&r,NoKey);

  DDSetColorKey(lpDDSMap,RGB(0,255,0));

  DDSetColorKey(lpDDSMouse,RGB(0,255,0));

  

  寫到這裡,也該休息一下了。

  reader:“這人怎麼這樣不負責任,總是寫的沒頭沒尾的!#$%*^*”

  weter:“先賣個關子,下一篇章中我們會進入到具體的功能的實現上,到底是怎麼樣完成圖片的裁減的工作的?他的原理是怎麼樣的?”

  預聽後事如何,且待下回分解。

  

  第四回:

  今天是最後一話了,而且廢話了這麼久都沒有切入主題,偶對不住大家啦,今天我們就正兒八經的的進入這次我們這個冗長的故事的核心的部分了,同時也是最後一個部分。

  

  書歸正傳,在direct程式設計裡面有兩個比較重要的函式,也是使用頻率相當高的兩個函式,在進入主題前我們必須先介紹這兩個函式,我們這個程式裡面也是用了他們。

  

  第一個很有用的函式是BltFast(),他的原型是

  HRESULT BltFast(

  DWORD dwX,

  DWORD dwY,

  LPDIRECTDRAWSURFACE lpDDSrcSurface,

  LPRECT lpSrcRect,

  DWORD dwTrans

  );

  

  下面將逐一介紹這幾個引數:

  (1)dwX和dwY:影像將被傳送到目標頁面何處。

  (2)lpDDSrcSurface:影像傳送操作的源頁面。目標頁面就是呼叫此方法的頁面。

  (3)lpSrcRect:一個 RECT (Rectangle,即矩形)結構的地址,指明源頁面上將被傳送的區域。如果該引數是NULL,整個源頁面將被使用。RECT結構在DirectDraw中非常常用,最好在程式中定義一個RECT型別的全域性變數,如rect,再象這樣寫一個函式:void MakeRect ()(關於這個函式就是我說的第二個非常有用的函式,我們在後面在專門對他進行介紹和說明)。

  (4)dwTrans:指定傳送型別。有如下幾種:

  DDBLTFAST_NOCOLORKEY

  指定進行一次普通的複製,不帶透明成分。

  DDBLTFAST_SRCCOLORKEY

  指定進行一次帶透明色的影像傳送,使用源頁面的透明色。

  DDBLTFAST_WAIT

  如果影像傳送器正忙,不斷重試直到影像傳送器準備好並傳送好時才返回。一般都使用這個引數。由於第四個引數比較長,而且有時候是兩個搭配起來用,所以大多數時候都是定義兩個全域性變數,後面使用起來就比較方便。

  DWORD SrcKey = DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT

  DWORD NoKey = DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT

  第二個很有用的函式就是我們前面提到的void MakeRect (),這一般是一個自定義函式,我們可以這樣定義他:

  

  void MakeRect (int left, int top, int right, int bottom)

  {

  rect.bottom = bottom;

  rect.left = left;

  rect.right = right;

  rect.top = top;

  }

  

  主要是確定了這個r結構的四個邊際。

  所以要裁減一副圖片到一個頁面中就很簡單了,是不是^_^,舉個例子:我們要貼第一回的哪個背景到SPrimary這個主頁面裡,就可以這樣

  MakeRect(0,0,640,480);

  lpDDSBuffer->BltFast(0,0,lpDDSPrimary,&r,NoKey);

  

  

  核心部分

  

  因為哪個背景的大小是640*480,所以我們的右邊際是640,下邊際是480,最後在利用BltFast()函式貼出來就是了,而且沒有透明,這樣我們就可以貼圖了。

  

  可是怎麼樣裁減呢?其實也就沒什麼難度了,你想在MakeRect()這個函式里面我們改變要貼圖的大小不就可以貼同一幅圖裡任意位置的圖部分了嗎,這就是裁減了塞,然後我們設成變數,用滑鼠自定義貼的大小,就必須和windows的訊息迴圈機制聯合起來使用了塞,我們在mousedown的時候得到他的一個座標,在mouseup的時候得到他的另一個座標,將兩個座標之間的圖片貼出來就可以了塞。其實這個裁減程式的主要的核心技術就在這裡了,實現思想也就是這麼回事,簡單吧:),其他的都是一些旁支末節的東西了。不過我們還是要一一介紹完。

  

  ok,到這裡我們就可以單獨寫一個類出來,完成我們的圖片裁減和貼圖功能了,我們寫一個類叫draw.cpp,這裡我們還把他的標頭檔案draw.h寫出來。

  

  draw.h:

  #if !defined (draw_h)

  #define draw_h

  

  class draw

  {

  public:

  int x1;

  int y1;

  int x2;

  int y2;

  void Rectanglep(int x1, int y1, int width, int height);//做成一個滑鼠在螢幕移動矩形的函式

  void blt(int x1,int y1,int x2,int y2);//完成我們的圖片裁減功能

  };

  

  #endif

  

  draw.cpp:

  #include "main.h"

  

  void draw::blt(int x1,int y1,int x2,int y2)

  {

  x1=drawp.x1;

  y2=drawp.y1;

  x2=drawp.x2;

  y2=drawp.y2;

  MakeRect(x1,y1,x2,y2);

  lpDDSBuffer->BltFast(0,0,lpDDSMap,&r,SrcKey);

  }

  

  void draw::Rectanglep(int x1,int y1,int x2,int y2)

  {

  HDC hdc;

  lpDDSPrimary->GetDC(&hdc);//主頁面得到控制程式碼

  HPEN Red_Pen=CreatePen(PS_SOLID,0,RGB(0,255,0));//填充畫筆的顏色

  SelectObject(hdc,Red_Pen);//設定畫筆的型別

  Line(x1,y1,x1,y2,hdc);//畫線

  Line(x1,y1,x2,y1,hdc);

  Line(x2,y1,x2,y2,hdc);

  Line(x1,y2,x2,y2,hdc);

  lpDDSPrimary->ReleaseDC(hdc);//用完後釋放控制程式碼

  }

  

  這裡就是對這兩自定義函式的具體化了。

  第一個函式就是我們前面介紹的實現圖形的裁減的部分,而且定義了四個變數作為滑鼠取點的座標。

  第二個函式就是滑鼠在螢幕上運動畫出的軌跡,是由四條線組成的一個矩形,這裡用到了API函式作圖,也就是微軟給我們的函式(微軟什麼都給我們封裝好了,用起來還真是方便呀)。

  

  然後就是公共使用的函式的一個類,這裡面自定義的函式可以全部被自由的使用

  我們定義為

  

  publicfuction.cpp

  

  //direct的初始化,前面介紹過,可以參看前面的章節

  void init()

  {

  DDSURFACEDESC2 ddsd;

  DirectDrawCreateEx (NULL, (void **)&lpDD,IID_IDirectDraw7, NULL);

  lpDD->SetCooperativeLevel(hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);

  lpDD->SetDisplayMode( 640, 480, 32, 0, DDSDM_STANDARDVGAMODE );

  memset(&ddsd, 0, sizeof(DDSURFACEDESC2));

  ddsd.dwSize = sizeof( ddsd );

  ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;

  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;

  ddsd.dwBackBufferCount = 1;

  lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );

  

  ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

  lpDDSPrimary->GetAttachedSurface( &ddsd.ddsCaps, &lpDDSBuffer );

  

  ddsd.dwSize = sizeof( ddsd );

  ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-951812/,如需轉載,請註明出處,否則將追究法律責任。

相關文章