圖像的漸顯/漸隱被廣泛運用于圖像處理和多媒體娛樂軟件。本文基于Windows的調色板動畫和時間碼技術設計了通用的圖像漸顯和漸隱算法,并實現了其Visual
C++程序編碼。
一、調色板動畫
在Visual C++中實現調色板動畫依賴于MFC類庫提供的CPalette 類和CDC類中的若干成員函數,其基本步驟如下:
1.調用CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)函數創建邏輯調色板,注意將參數LPLOGPALETTE所指向的各顏色表項結構的peFlags域設置為PC_RESERVED,以防止其它窗口同該調色板匹配顏色;
2.調用CDC::SelectPalette和CDC::RealizePalette函數選擇和實現所創建的邏輯調色板;
3.調用CPalette::AnimatePalette函數改變顏色,實現調色板動畫;4.動畫完成后應恢復系統調色板。
二、時間碼定時
CWnd::SetTimer函數可設置一個系統時間碼,并指定每經過一定的時間間隔使Windows系統發送一個WM_TIMER消息到窗口的消息隊列中。窗口在每當接收到相應的WM_TIMER消息時做一定的處理,便實現了定時處理。
通常應在窗口的消息循環中接受和處理WM_TIMER消息,這樣將很難編制通用的定時操作。通用的定時操作應將定時處理封裝在一個函數中,而不與其它的代碼糾纏在一起。筆者實現這一技術的技巧是,在循環操作中截獲窗口消息,如消息為指定的時間碼消息,則進行定時處理;否則分發消息給窗口消息處理機制。如果定時操作已結束,則修改循環標志,退出循環。具體的代碼略。
三、漸顯
漸顯就是將顯示顏色由黑色(RGB(0,0,0))逐漸變化為圖像各像素的顏色的過程。下面的函數FadeIn通過對調色板顏色表項中的各顏色分量值先設為0,然后進行遞增,直到所有顏色值都恢復成原調色板中顏色值來實現漸顯。
//圖像漸顯效果
//參數:
// pWnd - 顯示圖像的窗口
// pPal - 調色板指針
// nDeta - 各顏色分量的減小量
// uTimeOut - 時間的變化量
void FadeIn(CWnd *pWnd,Cpalette *pPal,int nDeta,Uint uTimeOut)
{
//保留原來的調色板顏色表項
int nTotalColors = pPal->GetEntryCount();
PALETTEENTRY PaletteColors0[256];
pPal->GetPaletteEntries(0,nTotalColors,PaletteColors0);
//先將調色板表項中各顏色分量置為0
PALETTEENTRY PaletteColors1[256];
for(int i=0;iSetPaletteEntries(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;iAnimatePalette(0,nTotalColors,PaletteColors);
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
::ReleaseCapture();
pWnd->KillTimer(0x100);
//恢復原始調色板
pPal->SetPaletteEntries(0,nTotalColors,PaletteColors0);
pPal->AnimatePalette(0,nTotalColors,PaletteColors0);
}
四、漸隱
漸隱就是將顯示顏色由圖像各像素的顏色逐漸變化為黑色(RGB(0,0,0))的過程,即定時調用CPalette::AnimatePalette,每次將各邏輯表項的peRed、peGreen、peBlue值減小一個變化量,直到它們都為0。
下面的函數FadeOut通過對調色板顏色表項中的各顏色分量值進行遞減,直到所有顏色值都變成0(即黑色)來實現漸隱。
//圖像漸隱效果
//參數:
// pWnd - 顯示圖像的窗口
// pPal - 調色板指針
// nDeta - 各顏色分量的減小量
// uTimeOut-時間的變化量
void FadeOut(CWnd *pWnd,CPalette
*pPal,int nDeta,Uint uTimeOut)
{
//保留原來的調色板顏色表項
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<nTotalColors;++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,則結束漸隱
bDone = bRedZero && bGreenZero && bBlueZero;
//使系統改變調色板
pPal->AnimatePalette(0,nTotalColors,PaletteColors);
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
::ReleaseCapture();
pWnd->KillTimer(0x100);
//恢復原始調色板
pPal->SetPaletteEntries(0,nTotalColors,PaletteColors0);
pPal->AnimatePalette(0,nTotalColors,PaletteColors0);
}