用Visual C++實現圖象漸顯和漸隱 (轉)
用Visual C++實現圖象漸顯和漸隱
周長發
摘 要 圖象的漸顯/漸隱被廣泛運用與圖象處理和多媒提娛樂。本文基於的調色盤動畫和時間碼技術設計了通用的圖象漸顯和漸隱演算法,並實現了其Visual C++編碼。
關鍵詞 漸顯、漸隱、調色盤、調色盤動畫、時間碼
圖象的漸顯/漸隱是十分重要的圖象效果,廣泛運用於圖象處理和多媒提娛樂軟體。漸顯/漸隱演算法設計的最大困難是速度控制,包括定時和改變圖象中各象素的顏色。如採用普通的全圖掃描演算法,則速度較慢,很難真正體現漸顯/漸隱效果。
利用Windows(3.x.95/98/NT)操作特殊的調色盤管理和時間碼定時機制能設計出有效的圖象漸顯/漸隱演算法。Windows提供一種被稱為調色盤動畫(palette animation)的顏色處理技術,它透過快速改變顏色調色盤中所選取的表項中的顏色能模擬顏色的變化。設定時間碼,定時該技術使圖象顏色漸變就能實現圖象的漸顯和漸隱。
一、調色盤動畫
在Visual C++中實現調色盤動畫依賴於MFC類庫提供的CPalette類和CDC類中的若干成員,其基本步驟如下:
- 呼叫CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)函式建立邏輯調色盤,注意將引數LPLOGPALETTE所指向的各顏色表項結構的peFlags域設定為PC_RESERVED,以防止其它視窗同該調色盤匹配顏色。;
- 呼叫CDC::Palette和CDC::RealizePalette函式選擇和實現所建立的邏輯調色盤;
- 呼叫CPalette::AnimatePalette函式改變顏色,實現調色盤動畫;
- 動畫完成後應恢復系統調色盤。
CPalette::AnimatePalette是其中最關鍵的函式,其原型如下:
void AnimatePalette(
UINT nStartIndex, // 起始的表項號
UINT nNumEntries, // 變化的表項數
LPPALETTEENTRY lpPaletteColors ); // 邏輯調色盤表項指標
lpPaletteColors為指向PALETTEENTRY結構的指標,其中著邏輯調色盤將要的顏色資訊。PALETTEENTRY結構定義如下:
typedef struct tagPALETTEENTRY { // pe
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY;
peRed、peGreen、peBlue分別表示邏輯調色盤項的R、G、B顏色分量值。peFlags 應被置為PC_RESERVED 。
nStartIndex為lpPaletteColors中將變化的起始表項號,nNumEntries 為lpPaletteColors中將變化的表項數。
二、時間碼定時
CWnd::SetTimer函式可設定一個系統時間碼,並指定每經過一定的時間間隔使Windows系統傳送一個WM_TIMER訊息到視窗的訊息佇列中。視窗在每當接收到相應的WM_TIMER訊息時做一定的處理,便實現了定時處理。
通常應在視窗的訊息迴圈中接受和處理WM_TIMER訊息,這樣將很難編制通用的定時操作。通用的定時操作應將定時處理封裝在一個函式中,而不與其它的程式碼糾纏在一起。筆者實現這一技術的技巧是,在迴圈操作中截獲視窗訊息,如訊息為指定的時間碼訊息,則進行定時處理;否則分發訊息給視窗訊息處理機制。如果定時操作已結束,則修改迴圈標誌,退出迴圈。具體的程式碼如下:
………………………………
// 設定時間碼,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)
{
…………………..
定時操作程式碼
…………………..
// 如定時操作完成,則設定迴圈標誌,結束操作
if (定時操作完成)
bDone = TRUE;
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
// 釋放滑鼠
::ReleaseCapture();
// 刪除時間碼
pWnd->KillTimer(0x100);
…………………………..
函式PeekMessage截獲視窗訊息,TranslateMessage和DispatchMessage函式解釋和分發除指定時間碼訊息之外的所有訊息,以避免丟失訊息。
三、漸顯
漸顯就是將顯示顏色由黑色(RGB(0, 0, 0))逐漸變化為圖象各象素的顏色的過程。開始時呼叫CPalette::GetPaletteEntries函式儲存圖象調色盤的各邏輯表項資訊,然後呼叫CPalette::SetPaletteEntries函式將邏輯調色盤中各邏輯表項的peRed、peGreen、peBlue置為0,定時呼叫CPalette::AnimatePalette,每次將各邏輯表項的peRed、peGreen、peBlue值增加一個變化量,直到它們分別等於圖象邏輯調色盤中各邏輯表項的peRed、peGreen、peBlue值。
下面的函式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; 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; } // 直到恢復原始值結束 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); }
四、漸隱
漸隱就是將顯示顏色由圖象各象素的顏色逐漸變化為黑色(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 { 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); }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988832/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- canvas繪製小球漸隱漸現Canvas
- Qt實現控制元件的漸隱漸現動效QT控制元件
- 短視訊直播原始碼,實現頂部導航欄背景圖片漸隱漸現效果原始碼
- CSS3圓形漸隱漸現迴圈出現CSSS3
- Dreamweaver網頁元素怎麼製作漸隱漸現效果教程網頁
- css3實現文字線性漸變,css3實現背景漸變CSSS3
- 循序漸進的用js實現一個bind()JS
- 使用 CSS 實現漸變效果CSS
- CSS和SVG實現文字漸變、描邊、投影CSSSVG
- CSS實現好看的文字漸變CSS
- CSS 實現字型顏色漸變CSS
- 她漸行漸遠
- 【譯】更多關於漸進式圖片載入的實現
- Dreamweaver製作滑鼠經過圖片漸漸變暗效果教程
- 精通Visual C++圖象程式設計------讀書筆記8C++程式設計筆記
- 精通Visual C++圖象程式設計---讀書筆記6.2C++程式設計筆記
- 精通Visual C++圖象程式設計---讀書筆記6.1C++程式設計筆記
- 精通Visual C++圖象程式設計---讀書筆記5C++程式設計筆記
- 如何實現css漸變圓角邊框CSS
- 使用canvas來完成線性漸變和徑向漸變的功能Canvas
- css文字顏色漸變的3種實現CSS
- 隨著國內“穩增長”政策效果逐漸顯現,經濟和經濟預期將出現邊際好轉
- 務實發展,循序漸進
- 實戰Forge Viewer漸進應用 - 當Xamarin遇上WebAssemblyViewWeb
- 圖片漸進式載入最佳化實踐指南
- 純CSS漸變繪製 Chrome 圖示CSSChrome
- flutter仿微信底部圖示漸變Flutter
- 系統漸漸淪為“屎山”,原因是..
- 搜尋引擎漸行漸遠,未來路在何方
- js顯式轉換和隱式轉換JS
- WePack —— 助力企業漸進式 DevOps 轉型dev
- 緬懷那些正漸行漸遠的程式語言
- css奇技淫巧-色彩漸變與動態漸變CSS
- css實現動態陰影、蝕刻文字、漸變文字CSS
- [譯] Android 實現顏色漸變的一個小 tipAndroid
- Android 沉浸式狀態列 漸變顏色的實現Android
- Table tr 奇數偶數行漸變色Jquery實現jQuery
- app直播原始碼,xml實現由上而下的顏色漸變APP原始碼XML
- 直播帶貨原始碼,商品頁面跳轉顯示白底, 新增漸變動畫原始碼動畫