用VC++实现图像渐显和渐隐

发表于:2007-07-04来源:作者:点击数: 标签:
周长发 图像的渐显/渐隐被广泛运用于图像处理和多媒体娱乐软件。本文基于 Windows 的调色板动画和时间码技术设计了通用的图像渐显和渐隐算法,并实现了其Visual C++程序编码。 一、调色板动画 在Visual C++中实现调色板动画依赖于MFC类库提供的CPalette
周长发

  图像的渐显/渐隐被广泛运用于图像处理和多媒体娱乐软件。本文基于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);

} 

原文转自:http://www.ltesting.net