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