摘要圖象的漸顯/漸隱被廣泛運用與圖象處理和多媒體娛樂軟件,
用Visual C++實現(xiàn)圖象漸顯和漸隱.net
。本文基于 Windows的調(diào)色板動畫和時間碼技術設計了通用的圖象漸顯和漸隱算法,并實 現(xiàn)了其VisualC++程序編碼。 關鍵詞漸顯、漸隱、調(diào)色板、調(diào)色板動畫、時間碼 圖象的漸顯/漸隱是十分重要的圖象效
摘 要 圖象的漸顯/漸隱被廣泛運用與圖象處理和多媒體娛樂軟件。本文基于
Windows的調(diào)色板動畫和時間碼技術設計了通用的圖象漸顯和漸隱算法,并實
現(xiàn)了其Visual C++程序編碼。
關鍵詞 漸顯、漸隱、調(diào)色板、調(diào)色板動畫、時間碼
圖象的漸顯/漸隱是十分重要的圖象效果,廣泛運用于圖象處理和多媒提娛樂
軟件。漸顯/漸隱算法設計的最大困難是速度控制,包括定時和快速改變圖象
中各象素的顏色。如采用普通的全圖掃描算法,則速度較慢,很難真正體現(xiàn)
漸顯/漸隱效果。
利用Windows(3.x.95/98/NT)操作系統(tǒng)特殊的調(diào)色板管理和時間碼定時機制
能設計出有效的圖象漸顯/漸隱算法。Windows提供一種被稱為調(diào)色板動畫
(palette animation)的顏色處理技術,它通過快速改變顏色調(diào)色板中所選
取的表項中的顏色能模擬顏色的變化。設置時間碼,定時調(diào)用該技術使圖象
顏色漸變就能實現(xiàn)圖象的漸顯和漸隱。
一、調(diào)色板動畫
在Visual C++中實現(xiàn)調(diào)色板動畫依賴于MFC類庫提供的CPalette類和CDC類中
的若干成員函數(shù),其基本步驟如下:
調(diào)用CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)函數(shù)創(chuàng)建邏輯
調(diào)色板,注意將參數(shù)LPLOGPALETTE所指向的各顏色表項結(jié)構(gòu)的peFlags域設置
為PC_RESERVED,以防止其它窗口同該調(diào)色板匹配顏色。;
調(diào)用CDC::SelectPalette和CDC::RealizePalette函數(shù)選擇和實現(xiàn)所創(chuàng)建的
邏輯調(diào)色板;
調(diào)用CPalette::AnimatePalette函數(shù)改變顏色,實現(xiàn)調(diào)色板動畫;
動畫完成后應恢復系統(tǒng)調(diào)色板。
CPalette::AnimatePalette是其中最關鍵的函數(shù),其原型如下:
void AnimatePalette(
UINT nStartIndex, // 起始的表項號
UINT nNumEntries, // 變化的表項數(shù)
LPPALETTEENTRY lpPaletteColors ); // 邏輯調(diào)色板表項指針
lpPaletteColors為指向PALETTEENTRY結(jié)構(gòu)的指針,其中存儲著邏輯調(diào)色
板將要更新的顏色信息。PALETTEENTRY結(jié)構(gòu)定義如下:
typedef struct tagPALETTEENTRY { // pe
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
peRed、peGreen、peBlue分別表示邏輯調(diào)色板項的R、G、B顏色分量值。
peFlags 應被置為PC_RESERVED 。
nStartIndex為lpPaletteColors中將變化的起始表項號,nNumEntries 為
lpPaletteColors中將變化的表項數(shù)。
二、時間碼定時
CWnd::SetTimer函數(shù)可設置一個系統(tǒng)時間碼,并指定每經(jīng)過一定的時間間隔
使Windows系統(tǒng)發(fā)送一個WM_TIMER消息到窗口的消息隊列中。窗口在每當接收
到相應的WM_TIMER消息時做一定的處理,便實現(xiàn)了定時處理。
通常應在窗口的消息循環(huán)中接受和處理WM_TIMER消息,這樣將很難編制通用的
定時操作。通用的定時操作應將定時處理封裝在一個函數(shù)中,而不與其它的代
碼糾纏在一起。筆者實現(xiàn)這一技術的技巧是,在循環(huán)操作中截獲窗口消息,如
消息為指定的時間碼消息,則進行定時處理;否則分發(fā)消息給窗口消息處理機
制。如果定時操作已結(jié)束,則修改循環(huán)標志,退出循環(huán)。具體的代碼如下:
………………………………
// 設置時間碼,pWnd為處理定時操作的窗口對象指針
pWnd->SetTimer(0x100, uTimeOut, NULL);
// 屏蔽鼠標操作,使定時操作不受影響
pWnd->SetCapture();
// 開始定時操作
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (msg.message == WM_TIMER && msg. WParam == 0x100)
…………………..
定時操作代碼
…………………..
// 如定時操作完成,則設置循環(huán)標志,結(jié)束操作
if (定時操作完成)
bDone = TRUE;
::TranslateMessage(&msg);
::DispatchMessage(&msg);
// 釋放鼠標
::ReleaseCapture();
// 刪除時間碼
pWnd->KillTimer(0x100);
…………………………..
函數(shù)PeekMessage截獲窗口消息,TranslateMessage和DispatchMessage函數(shù)解釋
和分發(fā)除指定時間碼消息之外的所有消息,以避免丟失消息。
三、漸顯
漸顯就是將顯示顏色由黑色(RGB(0, 0, 0))逐漸變化為圖象各象素的顏色的過程。
開始時調(diào)用CPalette::GetPaletteEntries函數(shù)保存圖象調(diào)色板的各邏輯表項信息,
然后調(diào)用CPalette::SetPaletteEntries函數(shù)將邏輯調(diào)色板中各邏輯表項的peRed、
peGreen、peBlue置為0,定時調(diào)用CPalette::AnimatePalette,每次將各邏輯表項
的peRed、peGreen、peBlue值增加一個變化量,直到它們分別等于圖象邏輯調(diào)色板
中各邏輯表項的peRed、peGreen、peBlue值。
下面的函數(shù)FadeIn通過對調(diào)色板顏色表項中的各顏色分量值先設為0,然后進行遞增,
直到所有顏色值都恢復成原調(diào)色板中顏色值來實現(xiàn)漸顯。
// 圖象漸顯效果
// 參數(shù):
// pWnd - 顯示圖象的窗口
// pPal - 調(diào)色板指針
// nDeta - 各顏色分量的減小量
// uTimeOut - 時間的變化量
void FadeIn(CWnd *pWnd, CPalette *pPal, int nDeta, UINT uTimeOut)
// 保留原來的調(diào)色板顏色表項
int nTotalColors = pPal->GetEntryCount();
PALETTEENTRY PaletteColors0[256];
pPal->GetPaletteEntries(0, nTotalColors, PaletteColors0);
// 先將調(diào)色板表項中各顏色分量置為0
PALETTEENTRY PaletteColors1[256];
for (int i=0; i PaletteColors1[i].peRed = 0;
PaletteColors1[i].peGreen = 0;
PaletteColors1[i].peBlue = 0;
PaletteColors1[i].peFlags = PC_RESERVED;
pPal->SetPaletteEntries(0, nTotalColors, PaletteColors1);
pPal->AnimatePalette(0, nTotalColors, PaletteColors1);
// 設置時間碼
pWnd->SetTimer(0x100, uTimeOut, NULL);
// 開始漸顯
pWnd->SetCapture();
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (msg.message == WM_TIMER && msg.wParam == 0x100)
CClientDC dc(pWnd);
CPalette *pOldPal = dc.SelectPalette(pPal, FALSE);
dc.RealizePalette();
// 遞增各顏色分量
PALETTEENTRY PaletteColors[256];
pPal->GetPaletteEntries(0, nTotalColors, PaletteColors);
BOOL bRedZero=FALSE;
BOOL bGreenZero=FALSE;
BOOL bBlueZero=FALSE;
for (int i=0; i if (PaletteColors[i].peRed + nDeta <
PaletteColors0[i].peRed)
PaletteColors[i].peRed += nDeta;
bRedZero = FALSE;
else if (PaletteColors[i].peRed + 1 <
PaletteColors0[i].peRed)
PaletteColors[i].peRed++;
bRedZero = FALSE;
else
bRedZero = TRUE;
if (PaletteColors[i].peGreen + nDeta <
PaletteColors0[i].peGreen)
PaletteColors[i].peGreen += nDeta;
bGreenZero = FALSE;
else if (PaletteColors[i].peGreen + 1 <
PaletteColors0[i].peGreen)
PaletteColors[i].peGreen++;
bGreenZero = FALSE;
else
bGreenZero = TRUE;
if (PaletteColors[i].peBlue + nDeta <
PaletteColors0[i].peBlue)
PaletteColors[i].peBlue += nDeta;
bBlueZero = FALSE;
else if (PaletteColors[i].peBlue +1 <
PaletteColors0[i].peBlue)
PaletteColors[i].peBlue++;
bBlueZero = FALSE;
else
bBlueZero = TRUE;
// 直到恢復原始值結(jié)束
bDone = bRedZero && bGreenZero && bBlueZero;
// 使系統(tǒng)改變調(diào)色板
pPal->AnimatePalette(0, nTotalColors, PaletteColors);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
::ReleaseCapture();
pWnd->KillTimer(0x100);
// 恢復原始調(diào)色板
pPal->SetPaletteEntries(0, nTotalColors, PaletteColors0);
pPal->AnimatePalette(0, nTotalColors, PaletteColors0);
四、漸隱
漸隱就是將顯示顏色由圖象各象素的顏色逐漸變化為黑色(RGB(0, 0, 0))的
過程,即定時調(diào)用CPalette::AnimatePalette,每次將各邏輯表項的peRed、
peGreen、peBlue值減小一個變化量,直到它們都為0,
電腦資料
《用Visual C++實現(xiàn)圖象漸顯和漸隱.net》(http://www.msguai.com)。下面的函數(shù)FadeOut通過對調(diào)色板顏色表項中的各顏色分量值進行遞減,直到
所有顏色值都變成0(即黑色)來實現(xiàn)漸隱。
// 圖象漸隱效果
// 參數(shù):
// pWnd - 顯示圖象的窗口
// pPal - 調(diào)色板指針
// nDeta - 各顏色分量的減小量
// uTimeOut - 時間的變化量
void FadeOut(CWnd *pWnd, CPalette *pPal, int nDeta, UINT uTimeOut)
// 保留原來的調(diào)色板顏色表項
int nTotalColors = pPal->GetEntryCount();
PALETTEENTRY PaletteColors0[256];
pPal->GetPaletteEntries(0, nTotalColors, PaletteColors0);
// 設置時間碼
pWnd->SetTimer(0x100, uTimeOut, NULL);
// 開始漸隱
pWnd->SetCapture();
BOOL bDone = FALSE;
MSG msg;
while (! bDone)
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (msg.message == WM_TIMER && msg.wParam == 0x100)
CClientDC dc(pWnd);
CPalette *pOldPal = dc.SelectPalette(pPal, FALSE);
dc.RealizePalette();
PALETTEENTRY PaletteColors[256];
pPal->GetPaletteEntries(0, nTotalColors, PaletteColors);
BOOL bRedZero=FALSE;
BOOL bGreenZero=FALSE;
BOOL bBlueZero=FALSE;
// 遞減顏色分量
for (int i=0; i if (PaletteColors[i].peRed > nDeta)
PaletteColors[i].peRed -= nDeta;
bRedZero = FALSE;
else if (PaletteColors[i].peRed > 1)
PaletteColors[i].peRed--;
bRedZero = FALSE;
else
bRedZero = TRUE;
if (PaletteColors[i].peGreen > nDeta)
PaletteColors[i].peGreen -= nDeta;
bGreenZero = FALSE;
else if (PaletteColors[i].peGreen > 1)
PaletteColors[i].peGreen--;
bGreenZero = FALSE;
else
bGreenZero = TRUE;
if (PaletteColors[i].peBlue > nDeta)
PaletteColors[i].peBlue -= nDeta;
bBlueZero = FALSE;
else if (PaletteColors[i].peBlue > 1)
PaletteColors[i].peBlue--;
bBlueZero = FALSE;
else
bBlueZero = TRUE;
// 如所有顏色分量都為0,則結(jié)束漸隱
bDone = bRedZero && bGreenZero && bBlueZero;
// 使系統(tǒng)改變調(diào)色板
pPal->AnimatePalette(0, nTotalColors, PaletteColors);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
::ReleaseCapture();
pWnd->KillTimer(0x100);
// 恢復原始調(diào)色板
pPal->SetPaletteEntries(0, nTotalColors, PaletteColors0);
pPal->AnimatePalette(0, nTotalColors, PaletteColors0);
原文轉(zhuǎn)自:http://www.ltesting.net