Microsoft的針對與設備無關位圖(DIB位圖),在其WIN32 SDK的Multimedia中提供了一組繪制DIB位圖的高性能函數(shù)組──DrawDib函數(shù)組。DrawDib函數(shù)組是一組不依賴于圖形設備接口(GDI)函數(shù),而直接操作顯存的函數(shù)組。它們支持8位、16位、24位和32位圖象深度的DIB??偟膩碚f,DrawDib函數(shù)組類似于StretchDIBits函數(shù),它們都提供了將圖象拉伸和抖動的功能,然而,DrawDib函數(shù)組還支持圖象的解壓、數(shù)據(jù)流以及更多的顯示適配器。在某些情況下,DrawDib函數(shù)組還具有更大的優(yōu)越性。但是,在某些場合下,DrawDib函數(shù)組卻不能取代StretchDIBits函數(shù)。下面就DrawDib函數(shù)組和StretchDIBits函數(shù)使用的場合加以區(qū)別和說明:
顏色信息表格式。DrawDib函數(shù)組只支持顏色信息表格式為DIB_RGB_COLORS格式的圖象,如果要顯示以DIB_PAL_COLORS或DIB_PAL_INDICES格式的圖象,則必須用StretchDIBits函數(shù)。
光柵操作模式。DrawDib函數(shù)組只能使用SRCCOPY光柵操作模式,如果要求不僅僅使用SRCCOPY模式的話,只能用StretchDIBits函數(shù)。同樣地,如果要使用其他光柵操作,例如XOR,只能用StretchDIBits函數(shù)。
視頻及動畫回放的質(zhì)量。DrawDib函數(shù)組支持數(shù)據(jù)流應用,諸如視頻片和動畫序列,它比StretchDIBits函數(shù)提供了更高的圖象質(zhì)量以及對回放過程的改進。
顯示適配器。DrawDib函數(shù)組比StretchDIBits函數(shù)支持更多的顯示適配器。DrawDib函數(shù)組支持使用4位圖象深度提供16色調(diào)色板的VGA適配器,使用8位圖象深度提供256色調(diào)色板的SVGA適配器和使用16位、24位和32位圖象深度提供成千上萬種顏色的真彩色適配器。DrawDib函數(shù)組還使用了受限制的潛在能力提高了圖象在顯示適配器上的速度和質(zhì)量。例如,當使用8位的顯示適配器時,DrawDib函數(shù)組有效地將真彩色圖象抖動為256色;同樣的,使用4位的顯示適配器時,它們也將8位深度的圖象抖動成4位。
圖象拉伸。正如StretchDIBits一樣,DrawDib函數(shù)組用源矩形和目的矩形來控制一個圖象顯示的部分??梢酝ㄟ^改變源矩形和目的矩形的位置和大小來裁剪一幅圖象不需要的部分和拉伸某部分。如果顯示驅動不支持圖象拉伸,那么DrawDib函數(shù)組提供了比StretchDIBits函數(shù)更有效的拉伸能力。
壓縮圖象。DrawDib函數(shù)組支持好幾種壓縮和解壓方法,其中包括游程編碼,JPEG,Cinepak,411YUV和Indeo™。
DrawDib的操作
通過使用DrawDibOpen函數(shù)初始化DrawDib函數(shù)組。DrawDibOpen負責裝載動態(tài)連接庫(DLL),申請內(nèi)存資源,DrawDib設備環(huán)境(DC),并且維持初始化相關的設備環(huán)境計數(shù)。DrawDibOpen同時返回一個其它DrawDib函數(shù)所需要使用的新的DC句柄。
當使用完DrawDib DC后,可以用DrawDibClose函數(shù)釋放它。DrawDibClose同時減少存取DLL的應用的計數(shù)。在應用程序中,DrawDibClose函數(shù)應是最后的DrawDib操作。
可以創(chuàng)建任意多的DrawDib DC,也可以同時使用多個DrawDib DC來繪制幾幅位圖。在應用程序中可以創(chuàng)建多個不同性質(zhì)的DrawDib DC,這樣就可以選擇最合適的DC設置。例如,在同一應用程序中,創(chuàng)建兩個不同的DrawDib DC,一個用來顯示圖象的正常分辨率,另一個用來顯示圖象的放大部分。
為了更有效地運行,DrawDib函數(shù)組需要知道顯示適配器及其驅動的信息。顯示配置信息是在第一次使用包含DrawDib函數(shù)組的DLL時,對顯示適配器通過了一系列的測試之后得到的。DrawDib函數(shù)組的所有應用都要用到這個配置信息??梢酝ㄟ^調(diào)用DrawDibProfileDisplay函數(shù)來強制重新進行這些測試。
通常,取得和保存顯示配置是一次性的事件。如果配置信息發(fā)現(xiàn)在這個系統(tǒng)中安裝了另一個顯示驅動時,DrawDib則重新進行測試。
圖象再現(xiàn)
創(chuàng)建了DrawDib DC后,就可以用DrawDibDraw函數(shù)將DIB繪至屏幕。當在8位深度的顯示適配器上顯示真彩色圖象時,DrawDib將自動地抖動圖象。
DrawDib也透明地支持視頻壓縮器。當顯示壓縮位圖時,可通過DrawDibGetBuffer函數(shù)得到包含了解壓圖象數(shù)據(jù)的緩沖區(qū)。如果位圖是未壓縮的,則DrawDibGetBuffer返回NULL。在應用程序中應自己區(qū)分位圖是否壓縮。
可用DrawDibUpdate宏來刷新一幅圖象的整體或一部分的顯示。
圖象序列
當DrawDibDraw函數(shù)同DrawDibBegin函數(shù)一起運用時,可以顯示相同尺寸和格式的位圖序列。DrawDib通過DrawDibBegin準備繪圖的DrawDib DC來提高DrawDibDraw的效率。如果,應用程序沒有調(diào)用DrawDibBegin,那么DrawDibDraw會在繪圖前隱含地執(zhí)行DrawDibBegin。
DrawDibBegin給DrawDibDraw提供了DrawDib的DC,DC的句柄,BITMAPINFOHEADER結構的地址和源矩形及目的矩形的尺寸。當要顯示一個位圖序列時,DrawDibDraw要檢查序列中的每幅圖象的這些值。如果DrawDibDraw檢測到這些值有任何變化,它將隱含地再次調(diào)用DrawDibBegin來調(diào)整DrawDib DC的設置。
當調(diào)用完DrawDibBegin后,就可以指定一個或多個適當?shù)臉酥緛碚{(diào)用DrawDibDraw繪制圖象序列。只要DC句柄未改變,就可指定DDF_SAME_HDC標志;下列參數(shù)未改變,就可指定DDF_SAME_DRAW標志:BITMAPINFOHEADER結構的地址和源矩形及目的矩形的尺寸。
可以通過在DrawDibEnd后跟另一個DrawDibBegin調(diào)用來更新前一個DrawDibBegin設置的標志。DrawDibEnd清除了當前的DrawDib DC的標志和設置。后續(xù)的調(diào)用DrawDibBegin將重新初始化DrawDib DC,并重新設置適當?shù)臉酥竞驮O置。然而,只要至少改變了以下任一個當前的標志設置:BITMAPINFOHEADER結構的地址或是源矩形或目的矩形的尺寸,也可不使用DrawDibEnd而直接調(diào)用DrawDibBegin來更新一個DrawDib DC。
通過使用DrawDibStart和DrawDibStop函數(shù),可以提高使用壓縮圖象的數(shù)據(jù)流操作(如回放一個視頻片)的DrawDibDraw的效率。DrawDibStart通過發(fā)送一個消息告訴視頻管理器(VCM)準備DrawDib DC來接受一個圖象流。當流結束時,DrawDibStop發(fā)送一個消息給VCM來指示它釋放申請的資源。
需要注意的是,在應用程序中必須確定源矩形和目的矩形的寬度和高度;然而卻并不需要確定這些矩形的起點。應用程序可以重新DrawDibDraw中的起點坐標來使用圖象的不同部分或更新顯示的不同部分。
DrawDib函數(shù)組需要響應兩條調(diào)色板消息:WM_QUERYNEWPALETTE和WM_PALETTECHANGED。如果應用程序未注意到調(diào)色板,就需要對這些消息都增加一個各自的消息處理。
通過使用DrawDibRealize函數(shù)可在當前DC中實現(xiàn)當前DrawDib的調(diào)色板。應當在響應WM_QUERYNEWPALETTE和WM_PALETTECHANGED消息時,或在用DrawDibDraw函數(shù)顯示一個圖象序列的準備過程中實現(xiàn)調(diào)色板。
可以用DrawDibSetPallette函數(shù)用另一個調(diào)色板的映射來繪一幅圖象。DrawDibSetPallette強迫DrawDib DC使用指定的調(diào)色板,而這會影響到圖象的質(zhì)量。例如,一個注意調(diào)色板的應用程序,可能已經(jīng)實現(xiàn)了一個調(diào)色板并需要阻止DrawDib實現(xiàn)它自己的調(diào)色板。應用程序可以通過DrawDibSetPalette來通知DrawDib調(diào)色板的使用。
通過使用DrawDibGetPallette函數(shù)可以獲得當前前景調(diào)色板的一個句柄。如果應用程序使用了當前前景調(diào)色板,它并沒有對調(diào)色板的完全使用權,另一個應用程序能夠使這個調(diào)色板句柄無效。當使用完畢后,應用程序不應該釋放調(diào)色板,那樣會使另一個應用程序不能使用調(diào)色板。
通過使用DrawDibChangPallete函數(shù)可以為它的調(diào)色板DrawDib來接收新的顏色值。在緊跟DrawDibChangPallete的后面的代碼里,可以為調(diào)色板顏色表指定新的值。當調(diào)用DrawDibChangPalette時,在DrawDib DC中未設置DDF_ANIMATE標志的話,可以通過使用DrawDibRealize來實現(xiàn)調(diào)色板和DrawDibDraw重繪圖象來實現(xiàn)調(diào)色板的改變。如果DDF_ANIMATE標志在DrawDib DC中設置了,就可以通過DrawDibDraw或DrawDibRealize來實現(xiàn)調(diào)色板和顯示著的位圖顏色的動畫。通過DrawDibEnd和DrawDibBegin可以DDF_ANIMATE標志。
如果釋放了被選入DC的DrawDib調(diào)色板,DC使用調(diào)色板時會報告一個GDI錯誤。相反,應該使用DrawDibSetPalette改變DrawDib DC來使用省缺調(diào)色板后另一調(diào)色板。
由于以下函數(shù)會釋放DrawDib調(diào)色板,所以,除非調(diào)色板不被DC選中不應使用:DrawDibEnd,DrawDibClose和DrawDibBegin。同樣的,當使用了相同的DrawDib DC,但指定了不同的繪制參數(shù)(lpbi,dxDst,dyDst,dxSrc或dySrc)或不同格式時,DrawDibDraw也會釋放調(diào)色板。
時間計算
作為調(diào)試應用程序的一部分,調(diào)用DrawDibTime函數(shù)可以得到一些關于完全重復特定次數(shù)DrawDib操作所需時間。DrawDibTime返回以下操作的時間:
繪制一幅位圖
解壓一幅位圖
抖動一幅位圖
拉伸一幅位圖
使用BitBlt函數(shù)變換一幅位圖
使用StrecthDIBits函數(shù)變換一幅位圖
得到返回值后,DrawDibTime重新設置每項操作的計數(shù)和值。
注意,DrawDibTime只在DrawDib函數(shù)的調(diào)試版中可用。
DrawDib的使用
增加調(diào)色板消息處理
下面的例子說明了WM_PALETTECHANGED和WM_QUERYNEWPALETTE消息的處理。這個例子用了DrawDibRealize函數(shù)來進行WM_QUERYNEWPALETTE消息的處理。
應用程序應通過使目標窗口無效來讓DrawDibDraw函數(shù)重繪圖象來響應WM_QUERYNEWPALETTE消息。應用DrawDibRealize函數(shù)實現(xiàn)調(diào)色板來響應WM_PALETTECHANGED消息。
case WM_PALETTECHANGED:
if ((HWND) wParam == hwnd)
break;
case WM_QUERYNEWPALETTE:
hdc = GetDC(hwnd);
f = DrawDibRealize (hdd,hdc,FALSE) > 0;
ReleaseDC (hwnd,hdc);
if (f)
InvalidateRect ( hwnd,NULL,TRUE);
break;
顯示設備繪制
下面例子用DrawDibrealize函數(shù)在顯示一個位圖序列之前準備DrawDib DC.
hdc = GetDC(hwnd);
DrawDibBegin(hdd,hdc,dxDest,dyDest,lpbi,dxSrc,dySrc,NULL);
DrawDibRealize(hdd,hdc,fBackground);
DrawDibDraw(hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,
xSrc,ySrc,dxSrc,dySrc,DDF_SAME_DRAW|DDF_SAME_HDC);
DrawDibDraw(hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,
xSrc,ySrc,dxSrc,dySrc,DDF_SAME_DRAW|DDF_SAME_HDC);
DrawDibDraw(hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,
xSrc,ySrc,dxSrc,dySrc,DDF_SAME_DRAW|DDF_SAME_HDC);
ReleaseDC(hwnd,hdc);
調(diào)色板動畫
下面用了DrawDibRealize,DrawDibChangPalette和DrawDibDraw函數(shù)演示調(diào)色板動畫。
能夠用DrawDibBegin函數(shù)協(xié)同DrawDibChangepalette函數(shù)改變一幅位圖的顏色。首先,在調(diào)用DrawDibBegin時指定DDF_ANIMATE標志允許調(diào)色板改變;然后,用DrawDibChangePalette函數(shù)從調(diào)色板入口設置顏色表的值。
例如,如果lppe是一個包含新顏色的PALETTEENTRY隊列的地址,并且lpbi是在DrawDibBegin或DrawDibDraw中使用的LPBITMAPINFOHEADER結構,則后面的程序片段更新DIB的顏色表。
hdc = GetDC(hwnd);
DrawDibBegin(hdd,…,DDF_ANIMATE);
DrawDibRealize(hdd,hdc,fBackground);
DrawDibDraw(hdd,hdc,…,DDF_SAME_DRAW|DDF_SAME_HDC);
//改變顏色調(diào)用
DrawDibChangePalette(hdd,iStart,iLen,lppe);
……
ReleaseDC(hwnd,hdc);
下面給出一個實例的關鍵片段加以說明:(在Visual C++ 4.2 下Windows95或Windows NT環(huán)境下通過。)
void CTestDrawDibView::OnDraw(CDC* pDC)
{
CTestDrawDibDoc* pDoc = GetDocument();//得到文檔指針
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
m_DibMem = pDoc->m_Buf;//得到DIB的內(nèi)存
if (m_DibMem == NULL)
{
//AfxMessageBox("Error in m_DibMem");
return;
}
UINT offset = pDoc->m_Off; //得到DIB數(shù)據(jù)的偏移
int xDst,yDst,dxDst,dyDst,xSrc,ySrc,dxSrc,dySrc;
LPBITMAPINFOHEADER lpbi;
LPVOID lpDibMem;
LPVOID lpbits=NULL;
// get the Windows width & height 得到窗口的寬高
RECT rect;
GetClientRect(&rect);
xDst = yDst = 0;
dxDst = rect.right - rect.left;
dyDst = rect.bottom - rect.top;
// Get Dib info得到DIB的信息
xSrc = ySrc =0;
lpDibMem = GlobalLock(m_DibMem);//鎖定內(nèi)存得到指針
lpbi = (LPBITMAPINFOHEADER)lpDibMem;//得到DIB信息
dxSrc = lpbi->biWidth;
dySrc = lpbi->biHeight;
lpbits = (LPSTR)lpDibMem + offset - sizeof(BITMAPFILEHEADER);
// Draw Dib繪DIB
HDC hdc = NULL;
hdc = pDC->m_hDC;
/*
// Using SetDIBToDevice使用SetDIBToDevice函數(shù)為對照
int line = SetDIBitsToDevice(hdc,
xDst,
yDst,
dxSrc,
dySrc,
xSrc,
ySrc,
0,
dySrc,
lpdib,//lpbits,
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS);
if(0 == line)
{
AfxMessageBox("Error in SetDIBsToDevice");
}
*/
/*
// Using StretchDIBits使用StretchDIBits函數(shù)為對照
int line = StretchDIBits(hdc,
xDst,
yDst,
dxDst,
dyDst,
xSrc,
ySrc,
dxSrc,
dySrc,
lpbits,
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS,
SRCCOPY);
if(0 == line)
{
AfxMessageBox("Error in SetDIBsToDevice");
}
*/
// Using DrawDib使用DrawDib
// Set Dawing flag設置繪制標志
UINT wFlags;
//標志意義參見前面的函數(shù)參考,以下兩個標志可繪出圖象,
//其余標志在這種情況下繪不出圖象。
wFlags = DDF_DONTDRAW;
//wFlags = DDF_NOTKEYFRAME;
HDRAWDIB hdd = DrawDibOpen();
if (hdd != NULL)
{
BOOL Suc = TRUE;
//具體參數(shù)請參見前面函數(shù)參考
Suc = DrawDibDraw(hdd,
hdc,
xDst,
yDst,
dxDst,
dyDst,
lpbi,
lpbits,
xSrc,
ySrc,
dxSrc,
dySrc,
wFlags);
if(Suc == FALSE) AfxMessageBox("DrawDib Failed");
/* //時間測試
DRAWDIBTIME time;
DrawDibTime(hdd ,&time);
char buf[256];
sprintf(buf,"Count %d\nDraw %d\nDecompress %d\n
Dither %d\nStretch %d\nBlt %d\n SetDIBits %d\n",
time.timeCount,time.timeDraw,
time.timeDecompress,time.timeDither,
time.timeStretch,time.timeBlt,
time.timeSetDIBits);
AfxMessageBox(buf);
*/
DrawDibClose(hdd);
}
else
AfxMessageBox("Error in DrawDibOpen");
GlobalUnlock(m_DibMem);//釋放DIB句柄
}
附:函數(shù)參考:
DrawDibBegin
這個DrawDib函數(shù)改變一個DrawDib DC的參數(shù)或初始化一個新的DrawDib DC.
BOOL DrawDibBegin(
HDRAWDIB hdd,
HDC hdc,
int dxDest,
int dyDest,
LPBITMAPINFOHEADER lpbi,
int dxSrc,
int dySrc,
UINT wFlags
);
參數(shù)
hdd DrawDib DC的句柄
hdc 繪圖DC的句柄。此參數(shù)為可選。
dxDst和dyDst 在MM_TEXT方式下目的矩形的寬度和高度。
lpbi 包含圖象格式的BITMAPINFOHEADER結構的地址。DIB顏色表緊跟圖象格式,并且biHeight成員必須為一正值。
dxSrc和dySrc 源矩形的寬度和高度(以象素為單位)。
wFlags 函數(shù)調(diào)用的可用標志。定義了以下的值:
DDF_ANIMATE 允許調(diào)色板動畫。如果這個值被設置,通過在LOGPALETTE結構中設置palPalEntry成員PC_RESERVED標志,則DrawDib保存了盡可能多的入口,調(diào)用drawDibChangePalette函數(shù)就可實現(xiàn)調(diào)色板動畫。如果應用程序用了DrawDibBegin函數(shù)協(xié)同DrawDibDraw函數(shù),最好在DrawDibBegin中設置這個值而不在DrawDibDraw中。
DDF_BACKGROUNDPAL 實現(xiàn)作為背景的調(diào)色板,保留當前顯示所使用的調(diào)色板不變。(這個值與DDF_SAME_HDC互斥。)
DDF_BUFFER 使DrawDib使用屏幕緩沖,這樣DDF_UPDATE才可使用。這關閉了解壓和直接繪屏。如果DrawDib不能創(chuàng)建一個脫屏緩沖,就解壓或直接繪屏。
DDF_DONTDRAW 當前圖象未繪,但已解壓。DDF_UPDATE能夠以后被用來繪圖象。這個標志取代了DDF_PREROLL標志。
DDF_FULLSCREEN 不被支持。
DDF_HALFTONE 不管DIB的調(diào)色板如何而把DIB抖動成標準調(diào)色板。如果應用程序用DrawDibBegin協(xié)同DrawDibDraw,在DrawDibBegin中設置這個值而不在DrawDibDraw中。
DDF_JUSTDRAWIT 用GDI繪這圖象。禁止DrawDib函數(shù)解壓,拉伸或抖動圖象。這實際上剝奪了DrawDib區(qū)別于StrechDIBits函數(shù)的能力。
DDF_SAME_DRAW 讓DrawDibDraw使用當前的繪制參數(shù)。只有當從使用DrawDibDraw或DrawDibBegin起,lpbi、dxDext、dyDest、dxSrc和dySrc就未改變才用這個值。這個標志取代了DDF_SAME_DIB和DDF_SAME_SIZE標志。
DDF_SAME_HDC 使用當前DC句柄以及與當前句柄相關聯(lián)的調(diào)色板。
DDF_UPDATE 最后緩存的圖象需要繪制。如果用這個值繪制失敗,則緩沖的圖象不在有效,并且在顯示被更新前,需要指定一幅新的圖象。
返回值
成功返回TRUE,否則FALSE。
注 這個函數(shù)準備由lpbi指定要繪往DC的DIB。圖象已經(jīng)拉伸成由dxDest和dyDest所指定的大小。如果dxDest和dyDest被設置成-1,DIB則被按原比例繪制。
可通過重新使用DrawDibBegin,指定新的標志和改變至少一個以下的設置:dxDest、dyDest、lpbi、dxSrc或dySrc來更新DrawDib DC的標志。
如果DrawDibBegin的參數(shù)未被改變,再次調(diào)用這個函數(shù)將不起作用。
DrawDibChangePalette
這個函數(shù)設置繪DIB所用的調(diào)色板。
BOOL DrawDibChangePalette(
HDRAWDIB hdd,
int iStart,
int iLen,
LPPALETTEENTRY lppe
);
參數(shù):
hdd DrawDib DC的句柄。
iStart 調(diào)色板開始數(shù)。
iLen 調(diào)色板的數(shù)目。
lppe 調(diào)色板陣列的地址。
返回值
成功返回TRUE,否則FALSE。
注 只有當當前DrawDib調(diào)色板是調(diào)用DrawDibRealize函數(shù)實現(xiàn)時,這個函數(shù)改變物理調(diào)色板。
如果顏色表沒有改變,下次沒有指定DDF_SAME_DRAW的DrawDibDraw函數(shù)將隱含地調(diào)用DrawDibBegin函數(shù)。
DrawDibClose
這個函數(shù)關閉一個DrawDib DC并釋放DrawDib申請的資源。
BOOL DrawDibClose(
HDRAWDIB hdd
);
參數(shù)
hdd DrawDib DC的句柄。
返回值
成功返回TRUE,否則FALSE。
DrawDibDraw
這個函數(shù)將DIB繪至屏幕。
BOOL DrawDibDraw(
HDRAWDIB hdd,
HDC hdc,
int xDst,
int yDst,
int dxDst,
int dyDst,
LPBITMAPINFOHEADER lpbi,
LPVOID lpBits,
int xSrc,
int ySrc,
int dxSrc,
int dySrc,
UINT wFlags
);
參數(shù)
hdd DrawDib DC的句柄。
hdc DC的句柄。
xDst和yDst 在MM_TEXT坐標系,目標矩形左上角的x和y坐標。
dxDst和dyDst 在MM_TEXT坐標系下,目標矩形的寬度和高度。如果dxDst為-1,則使用位圖的寬度;如果dyDst為-1,則使用位圖的高度。
lpbi 包含圖象格式的BITMAPINFOHEADER結構的地址。DIB的顏色表緊跟著格式后,并且biHeight成員必須為正值;DrawDibDraw不能繪制倒置的DIB。
lpbits 包含位圖位的緩沖的地址。
xSrc和ySrc 以象素為單位,源矩形左上角的x和y坐標。坐標(0,0)是位圖的左上角。
dxSrc和dySrc 以象素為單位,源矩形的寬度和高度。
wFlags 可用的繪圖標志。如下值被定義:
DDF_BACKGROUNDPAL 實現(xiàn)作為背景的調(diào)色板,保留當前顯示所使用的調(diào)色板不變。這個值只有當DDF_SAME_HDC未被設置時才有效。
DDF_DONTDRAW 當前圖象已解壓但未繪。這個標志取代了DDF_PREROLL標志。
DDF_FULLSCREEN 不被支持。
DDF_HALFTONE 不管DIB的調(diào)色板如何而把DIB抖動成標準調(diào)色板。如果應用程序使用了DrawDibBegin,在DrawDibBegin中設置而不在DrawDibDraw中。
DDF_HURRYUP 數(shù)據(jù)并不需要被繪(它可以被繪)并且DDF_UPDATE不用理會這個信息。DrawDib只有當需要去構建另一幀時才檢查這個值;否則,這個值被忽略。
這個值通常用來同步視頻和音頻。當同步數(shù)據(jù)時,應用程序應當用這個值發(fā)送圖象以防止驅動器需要緩沖幀來解壓后續(xù)幀。
DDF_NOTKEYFRAME DIB數(shù)據(jù)不是關鍵幀。
DDF_SAME_HDC 使用當前DC句柄以及與當前句柄相關聯(lián)的調(diào)色板。
DDF_SAME_DRAW 讓DrawDibDraw使用當前的繪制參數(shù)。只有當從使用DrawDibDraw或DrawDibBegin起,lpbi、dxDext、dyDest、dxSrc和dySrc就未改變才用這個值。DrawDibDraw經(jīng)常檢查這些參數(shù),如果它們改變了,DrawDibBegin則準備繪圖的DrawDib DC。這個標志取代了DDF_SAME_DIB和DDF_SAME_SIZE標志。
DDF_UPDATE 最后緩存的圖象需要繪制。如果用這個值繪制失敗,則緩沖的圖象不在有效,并且在顯示被更新前,需要指定一幅新的圖象。
返回值
成功返回TRUE,否則FALSE。
注 DDF_DONTDRAW使DrawDibDraw解壓但不顯示一幅圖象。一個調(diào)用DrawDibDraw的序列是指定DDF_UPDATE來顯示圖象。
如果DrawDib DC沒有指定一個屏幕緩沖,指定DDF_DONTDRAW會造成這幀被立即繪到屏幕。序列調(diào)用DrawDibDraw指定DDF_UPDATE會失敗。
盡管DDF_UPDAT和DDF_DONTDRAW可以在不同時間設置,它們可以一起用來創(chuàng)建脫屏圖象。當脫屏圖象完成后,可以調(diào)用DrawDibDraw來顯示圖象。
DrawDibEnd
這個函數(shù)清除由DrawDibBegin或DrawDibDraw函數(shù)設置的標志和DrawDib DC的其它設置。
BOOL DrawDibEnd(
HDRAWDIB hdd
);
參數(shù)
hdd 要釋放的DrawDib DC的句柄。
返回值
成功返回TRUE,否則FALSE。
DrawDibGetBuffer
這個函數(shù)清除由DrawDib用來解壓的緩沖的地址。
LPVOID DrawDibGetBuffer(
HDRAWDIB hdd,
LPBITMAPINFOHEADER lpbi,
DWORD dwSize,
DWORD dwFlags
);
參數(shù)
hdd 要釋放的DrawDib DC的句柄。
lpbi BITMAPINFO結構的地址。這個結構由BITMAPINFOHEADER結構和位圖使用的256色調(diào)色板所定義的顏色表。
dwSize 通過lpbi的BITMAPINFO結構所指的字節(jié)大小。
dwFlags 保留,必須為0。
返回值
返回緩沖的地址或者如果沒有用到緩沖返回NULL。如果lpbi不為NULL,它填充了一個描繪緩沖的BITMAPINFO的結構。
DrawDibGetPalette
這個函數(shù)清除由DrawDib DC所使用的調(diào)色板。
HPALETTE DrawDibGetPalette(
HDRAWDIB hdd
);
參數(shù)
hdd 要釋放的DrawDib DC的句柄。
返回值
成功返回一個調(diào)色板句柄,否則返回NULL。
注 這個函數(shù)假設DrawDib DC包含了一個有效的調(diào)色板,隱含著這樣的一個條件:對這個函數(shù)的調(diào)用必須在DrawDibDraw或DrawDibBegin函數(shù)之后。
DrawDibOpen
這個函數(shù)打開DrawDib庫為使用和創(chuàng)建一個繪圖的DrawDib DC作準備。
HDRAWDIB DrawDibOpen(VOID);
參數(shù)
這個函數(shù)不需要參數(shù)。
返回值
成功返回一個DrawDib DC的句柄,否則為NULL。
注 當同時繪多個DIB時,為同時在屏的每個圖象創(chuàng)建一個DrawDib DC。
DrawDibProfileDisplay
這個函數(shù)決定了當用DrawDib函數(shù)時顯示系統(tǒng)的設置。
BOOL DrawDibProfileDisplay(
LPBITMAPINFOHEADER lpbi
);
參數(shù)
lpbi 包含位圖信息的BITMAPINFOHEADER結構??梢酝ㄟ^指定NULL來確認配置信息是當前的。如果配置信息不是當前的,DrawDib會重新運行配置測試來得到當前設置信息。如果把這個參數(shù)設為NULL來調(diào)用DrawDibProfileDisplay返回值是沒有意義的。
返回值
返回值指出了這個顯示系統(tǒng)的最快繪制和拉伸能力。如果位圖格式不被支持,這個值為0或一個或更多的下列值:
PD_CAN_DRAW_DIB DrawDib能用這種格式繪圖象。拉伸可能被支持或不被支持。
PD_CAN_STRETCHDIB DrawDib能用這種格式拉伸或繪制圖象。
PD_STRETCHDIB _1_1_OK StretchDIBits用這種格式繪未拉伸的圖象快于另一種方式。
PD_STRETCHDIB _1_2_OK StretchDIBits用這種格式繪以1:2拉伸的圖象快于另一種方式。
PD_STRETCHDIB _1_N_OK StretchDIBits用這種格式繪以1:N拉伸的圖象快于另一種方式。
DrawDibRealize
這個函數(shù)為用指定DC實現(xiàn)DrawDib DC 的調(diào)色板。
UINT DrawDibRealize (
HDRAWDIB hdd ,
HDC hdc ,
BOOL fBackground
) ;
參數(shù)
hdd DrawDib DC hdd DrawDib DC的句柄。
hdc 包含調(diào)色板的DC的句柄。
fBackground 背景調(diào)色板標志。如果此值非零,此調(diào)色板為背景調(diào)色板。如果此值為零并且DC與另一個窗口相連,當窗口擁有輸入焦點時邏輯調(diào)色板變?yōu)楸尘罢{(diào)色板。(當窗口風格是CS_OWNDC或當DC是用GetDC函數(shù)得到的時,一個DC就與一個窗口相連)。
返回值
返回在系統(tǒng)調(diào)色板中映射了不同值的邏輯調(diào)色板中的入口值。如果發(fā)生了錯誤或沒有要更新的顏色,返回0。
注意
用DrawDibDraw函數(shù)并指定DDF_BACKGROUNDPAL標志來選擇DrawDib DC的調(diào)色板作背景調(diào)色板。
DrawDibSetPalette
這個函數(shù)設置繪DIB所用的調(diào)色板。
BOOL DrawDibSetPalette(
HDRAWDIB hdd ,
HPALETTE hpal
) ;
參數(shù)
hdd DrawDib DC的句柄。
hpal 調(diào)色板的句柄。指定NULL則使用缺省調(diào)色板。
返回值
成功返回TRUE,否則返回FALSE。
DrawDibStart
DrawDibStart函數(shù)為流回放準備 DrawDib DC。
BOOL DrawDibStart(
HDRAWDIB hdd ,
LONG rate
);
參數(shù)
hdd DrawDib DC的句柄。
rate 回放率 每幀以毫秒計。
返回值
成功返回TRUE,否則返回FALSE。
DrawDibStop
這個函數(shù)釋放用于流回放的DrawDib DC所占用的資源。
BOOL DrawDibStop(
HDRAWDIB hdd
);
參數(shù)
hdd DrawDib DC的句柄。
返回值
成功返回TRUE,否則返回FALSE。
DrawDibTime
這個函數(shù)得到關于繪制操作的時間和調(diào)試操作的時間信息。
BOOL DrawDibTime(
HDRAWDIB hdd,
LPDRAWDIBTIME lpddtime
) ;
參數(shù)
hdd DrawDib DC的句柄。
lpddtime DrawDibTime的結構地址。
返回值
成功返回TRUE,否則返回FALSE。
加入vfw32.lib 引用
#pragma comment(lib,"vfw32")
加入頭文件
#include "vfw.h"
頭文件中定義HDRAWDIB m_hDrawDib;
COLORREF* m_clrSrc;
CSize m_size;
cpp文件初始化
{
m_hDrawDib=NULL;
m_hDrawDib=DrawDibOpen();
HBITMAP hBmp=(HBITMAP)LoadImage(NULL,"bitmap.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HDC hMemDC=CreateCompatibleDC(NULL);
if(hMemDC)
{
BITMAP bm;
GetObject(hBmp,sizeof(bm),&bm);
m_size=CSize(bm.bmWidth,bm.bmHeight);
BITMAPINFOHEADER RGB32BITSBITMAPINFO= {sizeof(BITMAPINFOHEADER),bm.bmWidth,bm.bmHeight,
1,32,BI_RGB,0,0,0,0};
HBITMAP m_bmpSrc=CreateDIBSection(hMemDC,(BITMAPINFO*)&RGB32BITSBITMAPINFO,DIB_RGB_COLORS,(VOID**)&m_clrSrc,NULL,0);
if(m_bmpSrc)
{
HBITMAP hOldBmp=(HBITMAP)SelectObject(hMemDC,m_bmpSrc);
HDC hDC=CreateCompatibleDC(hMemDC);
if(hDC)
{
HBITMAP hOldBmp2=(HBITMAP)SelectObject(hDCm_(hBmp);
BitBlt(hMemDC,0,0,bm.bmWidth,bm.bmHeight,hDC,0,0,SRCCOPY);
SelectObject(hDC,hOldBmp2);
DeleteDC(hDC);
}
SelectObject(hMemDC,hOldBmp);
}
DeleteDC(hMemDC);
}
}
銷毀時
if(m_hDrawDib!=NULL)
{
DrawDibClose(m_hDrawDib);
m_hDrawDib=NULL;
}
if(m_bmpSrc!=NULL)
DeleteObject(m_bmpSrc);
實現(xiàn)馬賽克效果
if(m_bmpSrc==NULL||m_hDrawDib==NULL)return;
Invalidate();
int nTileSize=10;
int nTileNum=((m_size.cx+nTileSize-1)/nTileSize)*((m_size.cy+nTileSize-1)/nTileSize);
POINT *pt=new POINT[nTileNum];
int x=0;
int y=0;
int i;
for(i=0;i<nTileNum;i++)
{
pt[i].x=x;
pt[i].y=y;
x=x+nTileSize;
if(x>m_size.cx)
{
x=0;
y=y+nTileSize;
}
}
// 建立了nTileNum個馬賽克塊
BITMAPINFOHEADER RGB32BITSBITMAPINFO= {sizeof(BITMAPINFOHEADER),bm.bmWidth,bm.bmHeight,
1,32,BI_RGB,0,0,0,0};
CPaintDC dc(this);
DrawDibRealize(m_hDrawDib,dc.GetSafeHdc(),TRUE);
double fMax=RAND_MAX;
for(i=nTileNum-1;i>=0;i--)
{
int n=(int)((double)nTileNum*rand()/fMax);
x=pt[n].x;
y=pt[n].y;
DrawDibDraw(m_hDrawDib,dc.GetSafeHdc(),10+x,10+y,nTileSize,nTileSize,&RGB32BITSBITMAPINFO,(LPVOID)m_clrSrc,x,y,nTileSize,nTileSize,DDF_BACKGROUNDPAL);
pt[n].x=pt[i].x;
pt[n].y=pt[i].y ;
Sleep(20);
}
delete [] pc;
pc = NULL;
DrawDibDraw(m_hDrawDib,dc.GetSafeHdc(),10,10,m_size.cx,m_size.cy,&RGB32BITSBITMAPINFO,(LPVOID)m_clrSrc,0,0,m_size.cx,m_size.cy,DDF_BACKGROUNDPAL);
// 建立縱向百葉窗效果
if(m_bmpSrc==NULL||m_hDrawDib==NULL)return;
Invalidate();
BOOL bDone=FALSE;
int i=0,j;
BITMAPINFOHEADER REG32BITSBITMAPINFO= {sizeof(BITMAPINFOHEADER),bm.bmWidth,bm.bmHeight,1,32,BI_RGB,0,0,0,0,0};
CPaintDC dc(this);
DrawDibRealize(m_hDrawDib,dc.GetSafeHdc(),true);
for(i=0;i<20;i++)
{
for(j=i;j<m_size.cy;j+=20)
DrawDibDraw(m_hDrawDib,pDC->GetSafeHdc(),j,0,1,m_size.cy,®32BITSBITMAPINFO,(LPVOID)m_clrSrc, j,0,1,m_size.cy,DDF_BACKGROUNDPAL);
Sleep(200);
}
// 從右向左移動0
if(m_bmpSrc==NULL||m_hDrawDib==NULL)return;
Invalidate();
BOOL bDone=false;
int i=0;
BITMAPINFOHEADER RGB32BITSBITMAPINFO=
{sizeof(BITMAPINFOHEADER),m_size.cx,m_size.cy,1,32,BI_RGB,0,0,0,0,0};
CPaintDC dc(this);
while(!bDone)
{
if(i>m_size.cx)
{
i=m_size.cx;
bDone=true;
}
DrawDibRealize(m_hDrawDib,dc.GetSafeHdc(),true);
DrawDibDraw(m_hDrawDib,dc.GetSafeHdc(),10+m_size.cx-i,10,i,
m_size.cy,&RGB32BITSBITMAPINFO,(LPVOID)m_clrSrc,
0,0,i,m_size.cy,DDF_BACKGROUNDPAL);
i+=10;
Sleep(50);
}