📄 csdn_文档中心_用vc 实现图象渐显和渐隐.htm
字号:
<TD height=10></TD></TR></TBODY></TABLE><!--文章说明信息结束//-->
<TABLE border=0 width=600>
<TBODY>
<TR>
<TD align=left><BR>
<DIV>作者: 周长发<BR><BR>摘 要
图象的渐显/渐隐被广泛运用与图象处理和多媒提娱乐软件。本文基于Windows的调色板动画和时间码技术设计了通用的图象渐显和渐隐算法,并实现了其Visual
C++程序编码。<BR><BR>关键词
渐显、渐隐、调色板、调色板动画、时间码<BR><BR>图象的渐显/渐隐是十分重要的图象效果,广泛运用于图象处理和多媒提娱乐软件。渐显/渐隐算法设计的最大困难是速度控制,包括定时和快速改变图象中各象素的颜色。如采用普通的全图扫描算法,则速度较慢,很难真正体现渐显/渐隐效果。<BR><BR>利用Windows(3.x.95/98/NT)操作系统特殊的调色板管理和时间码定时机制能设计出有效的图象渐显/渐隐算法。Windows提供一种被称为调色板动画(palette
animation)的颜色处理技术,它通过快速改变颜色调色板中所选取的表项中的颜色能模拟颜色的变化。设置时间码,定时调用该技术使图象颜色渐变就能实现图象的渐显和渐隐。<BR><BR>一、调色板动画<BR><BR>在Visual
C++中实现调色板动画依赖于MFC类库提供的CPalette类和CDC类中的若干成员函数,其基本步骤如下:<BR><BR>调用CPalette::CreatePalette(LPLOGPALETTE
lpLogPalette)函数创建逻辑调色板,注意将参数LPLOGPALETTE所指向的各颜色表项结构的peFlags域设置为PC_RESERVED,以防止其它窗口同该调色板匹配颜色。;
<BR>调用CDC::SelectPalette和CDC::RealizePalette函数选择和实现所创建的逻辑调色板;
<BR>调用CPalette::AnimatePalette函数改变颜色,实现调色板动画; <BR>动画完成后应恢复系统调色板。
<BR>CPalette::AnimatePalette是其中最关键的函数,其原型如下:<BR><BR>void
AnimatePalette(<BR><BR>UINT nStartIndex, // 起始的表项号<BR><BR>UINT
nNumEntries, // 变化的表项数<BR><BR>LPPALETTEENTRY lpPaletteColors ); //
逻辑调色板表项指针<BR><BR>lpPaletteColors为指向PALETTEENTRY结构的指针,其中存储着逻辑调色板将要更新的颜色信息。PALETTEENTRY结构定义如下:<BR><BR>typedef
struct tagPALETTEENTRY { // pe <BR><BR>BYTE peRed; <BR><BR>BYTE
peGreen; <BR><BR>BYTE peBlue; <BR><BR>BYTE peFlags; <BR><BR>}
PALETTEENTRY;
<BR><BR>peRed、peGreen、peBlue分别表示逻辑调色板项的R、G、B颜色分量值。peFlags
应被置为PC_RESERVED
。<BR><BR>nStartIndex为lpPaletteColors中将变化的起始表项号,nNumEntries
为lpPaletteColors中将变化的表项数。<BR><BR>二、时间码定时<BR><BR>CWnd::SetTimer函数可设置一个系统时间码,并指定每经过一定的时间间隔使Windows系统发送一个WM_TIMER消息到窗口的消息队列中。窗口在每当接收到相应的WM_TIMER消息时做一定的处理,便实现了定时处理。<BR><BR>通常应在窗口的消息循环中接受和处理WM_TIMER消息,这样将很难编制通用的定时操作。通用的定时操作应将定时处理封装在一个函数中,而不与其它的代码纠缠在一起。笔者实现这一技术的技巧是,在循环操作中截获窗口消息,如消息为指定的时间码消息,则进行定时处理;否则分发消息给窗口消息处理机制。如果定时操作已结束,则修改循环标志,退出循环。具体的代码如下:<BR><BR>………………………………<BR><BR>//
设置时间码,pWnd为处理定时操作的窗口对象指针<BR><BR>pWnd->SetTimer(0x100, uTimeOut,
NULL);<BR><BR>//
屏蔽鼠标操作,使定时操作不受影响<BR><BR>pWnd->SetCapture();<BR><BR>//
开始定时操作<BR><BR>BOOL bDone = FALSE;<BR><BR>MSG msg;<BR><BR>while (!
bDone)<BR><BR>{<BR><BR>if (::PeekMessage(&msg, NULL, 0, 0,
PM_REMOVE))<BR><BR>{<BR><BR>if (msg.message == WM_TIMER &&
msg. WParam ==
0x100)<BR><BR>{<BR><BR>…………………..<BR><BR>定时操作代码<BR><BR>…………………..<BR><BR>//
如定时操作完成,则设置循环标志,结束操作<BR><BR>if (定时操作完成)<BR><BR>bDone =
TRUE;<BR><BR>}<BR><BR>::TranslateMessage(&msg);<BR><BR>::DispatchMessage(&msg);<BR><BR>}<BR><BR>}<BR><BR>//
释放鼠标<BR><BR>::ReleaseCapture();<BR><BR>//
删除时间码<BR><BR>pWnd->KillTimer(0x100);<BR><BR>…………………………..<BR><BR>函数PeekMessage截获窗口消息,TranslateMessage和DispatchMessage函数解释和分发除指定时间码消息之外的所有消息,以避免丢失消息。<BR><BR>三、渐显<BR><BR>渐显就是将显示颜色由黑色(RGB(0,
0,
0))逐渐变化为图象各象素的颜色的过程。开始时调用CPalette::GetPaletteEntries函数保存图象调色板的各逻辑表项信息,然后调用CPalette::SetPaletteEntries函数将逻辑调色板中各逻辑表项的peRed、peGreen、peBlue置为0,定时调用CPalette::AnimatePalette,每次将各逻辑表项的peRed、peGreen、peBlue值增加一个变化量,直到它们分别等于图象逻辑调色板中各逻辑表项的peRed、peGreen、peBlue值。<BR><BR>下面的函数FadeIn通过对调色板颜色表项中的各颜色分量值先设为0,然后进行递增,直到所有颜色值都恢复成原调色板中颜色值来实现渐显。<BR><BR>//
图象渐显效果<BR><BR>// 参数:<BR><BR>// pWnd – 显示图象的窗口<BR><BR>// pPal –
调色板指针<BR><BR>// nDeta – 各颜色分量的减小量<BR><BR>// uTimeOut –
时间的变化量<BR><BR>void FadeIn(CWnd *pWnd, CPalette *pPal, int nDeta,
UINT uTimeOut) <BR><BR>{<BR><BR>// 保留原来的调色板颜色表项<BR><BR>int
nTotalColors = pPal->GetEntryCount();<BR><BR>PALETTEENTRY
PaletteColors0[256];<BR><BR>pPal->GetPaletteEntries(0,
nTotalColors, PaletteColors0);<BR><BR>//
先将调色板表项中各颜色分量置为0<BR><BR>PALETTEENTRY PaletteColors1[256];<BR><BR>for
(int i=0; i<nTotalColors;
++i)<BR><BR>{<BR><BR>PaletteColors1[i].peRed =
0;<BR><BR>PaletteColors1[i].peGreen =
0;<BR><BR>PaletteColors1[i].peBlue =
0;<BR><BR>PaletteColors1[i].peFlags =
PC_RESERVED;<BR><BR>}<BR><BR>pPal->SetPaletteEntries(0,
nTotalColors, PaletteColors1);<BR><BR>pPal->AnimatePalette(0,
nTotalColors, PaletteColors1);<BR><BR>//
设置时间码<BR><BR>pWnd->SetTimer(0x100, uTimeOut, NULL);<BR><BR>//
开始渐显<BR><BR>pWnd->SetCapture();<BR><BR>BOOL bDone =
FALSE;<BR><BR>MSG msg;<BR><BR>while (! bDone)<BR><BR>{<BR><BR>if
(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))<BR><BR>{<BR><BR>if
(msg.message == WM_TIMER && msg.wParam ==
0x100)<BR><BR>{<BR><BR>CClientDC dc(pWnd);<BR><BR>CPalette *pOldPal
= dc.SelectPalette(pPal,
FALSE);<BR><BR>dc.RealizePalette();<BR><BR>//
递增各颜色分量<BR><BR>PALETTEENTRY
PaletteColors[256];<BR><BR>pPal->GetPaletteEntries(0,
nTotalColors, PaletteColors);<BR><BR>BOOL
bRedZero=FALSE;<BR><BR>BOOL bGreenZero=FALSE;<BR><BR>BOOL
bBlueZero=FALSE;<BR><BR>for (int i=0; i<nTotalColors;
++i)<BR><BR>{<BR><BR>if (PaletteColors[i].peRed + nDeta
<<BR><BR>PaletteColors0[i].peRed)<BR><BR>{<BR><BR>PaletteColors[i].peRed
+= nDeta;<BR><BR>bRedZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peRed + 1
<<BR><BR>PaletteColors0[i].peRed)<BR><BR>{<BR><BR>PaletteColors[i].peRed++;<BR><BR>bRedZero
= FALSE;<BR><BR>}<BR><BR>else<BR><BR>bRedZero = TRUE;<BR><BR>if
(PaletteColors[i].peGreen + nDeta
<<BR><BR>PaletteColors0[i].peGreen)<BR><BR>{<BR><BR>PaletteColors[i].peGreen
+= nDeta;<BR><BR>bGreenZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peGreen + 1
<<BR><BR>PaletteColors0[i].peGreen)<BR><BR>{<BR><BR>PaletteColors[i].peGreen++;<BR><BR>bGreenZero
= FALSE;<BR><BR>}<BR><BR>else<BR><BR>bGreenZero = TRUE;<BR><BR>if
(PaletteColors[i].peBlue + nDeta
<<BR><BR>PaletteColors0[i].peBlue)<BR><BR>{<BR><BR>PaletteColors[i].peBlue
+= nDeta;<BR><BR>bBlueZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peBlue +1
<<BR><BR>PaletteColors0[i].peBlue)<BR><BR>{<BR><BR>PaletteColors[i].peBlue++;<BR><BR>bBlueZero
= FALSE;<BR><BR>}<BR><BR>else<BR><BR>bBlueZero =
TRUE;<BR><BR>}<BR><BR>// 直到恢复原始值结束<BR><BR>bDone = bRedZero
&& bGreenZero && bBlueZero;<BR><BR>//
使系统改变调色板<BR><BR>pPal->AnimatePalette(0, nTotalColors,
PaletteColors);<BR><BR>}<BR><BR>::TranslateMessage(&msg);<BR><BR>::DispatchMessage(&msg);<BR><BR>}<BR><BR>}<BR><BR>::ReleaseCapture();<BR><BR>pWnd->KillTimer(0x100);<BR><BR>//
恢复原始调色板<BR><BR>pPal->SetPaletteEntries(0, nTotalColors,
PaletteColors0);<BR><BR>pPal->AnimatePalette(0, nTotalColors,
PaletteColors0);<BR><BR>}<BR><BR>四、渐隐<BR><BR>渐隐就是将显示颜色由图象各象素的颜色逐渐变化为黑色(RGB(0,
0,
0))的过程,即定时调用CPalette::AnimatePalette,每次将各逻辑表项的peRed、peGreen、peBlue值减小一个变化量,直到它们都为0。<BR><BR>下面的函数FadeOut通过对调色板颜色表项中的各颜色分量值进行递减,直到所有颜色值都变成0(即黑色)来实现渐隐。<BR><BR>//
图象渐隐效果<BR><BR>// 参数:<BR><BR>// pWnd – 显示图象的窗口<BR><BR>// pPal –
调色板指针<BR><BR>// nDeta – 各颜色分量的减小量<BR><BR>// uTimeOut –
时间的变化量<BR><BR>void FadeOut(CWnd *pWnd, CPalette *pPal, int nDeta,
UINT uTimeOut) <BR><BR>{<BR><BR>// 保留原来的调色板颜色表项<BR><BR>int
nTotalColors = pPal->GetEntryCount();<BR><BR>PALETTEENTRY
PaletteColors0[256];<BR><BR>pPal->GetPaletteEntries(0,
nTotalColors, PaletteColors0);<BR><BR>//
设置时间码<BR><BR>pWnd->SetTimer(0x100, uTimeOut, NULL);<BR><BR>//
开始渐隐<BR><BR>pWnd->SetCapture();<BR><BR>BOOL bDone =
FALSE;<BR><BR>MSG msg;<BR><BR>while (! bDone)<BR><BR>{<BR><BR>if
(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))<BR><BR>{<BR><BR>if
(msg.message == WM_TIMER && msg.wParam ==
0x100)<BR><BR>{<BR><BR>CClientDC dc(pWnd);<BR><BR>CPalette *pOldPal
= dc.SelectPalette(pPal,
FALSE);<BR><BR>dc.RealizePalette();<BR><BR>PALETTEENTRY
PaletteColors[256];<BR><BR>pPal->GetPaletteEntries(0,
nTotalColors, PaletteColors);<BR><BR>BOOL
bRedZero=FALSE;<BR><BR>BOOL bGreenZero=FALSE;<BR><BR>BOOL
bBlueZero=FALSE;<BR><BR>// 递减颜色分量<BR><BR>for (int i=0;
i<nTotalColors; ++i)<BR><BR>{<BR><BR>if (PaletteColors[i].peRed
> nDeta)<BR><BR>{<BR><BR>PaletteColors[i].peRed -=
nDeta;<BR><BR>bRedZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peRed >
1)<BR><BR>{<BR><BR>PaletteColors[i].peRed--;<BR><BR>bRedZero =
FALSE;<BR><BR>}<BR><BR>else<BR><BR>bRedZero = TRUE;<BR><BR>if
(PaletteColors[i].peGreen >
nDeta)<BR><BR>{<BR><BR>PaletteColors[i].peGreen -=
nDeta;<BR><BR>bGreenZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peGreen >
1)<BR><BR>{<BR><BR>PaletteColors[i].peGreen--;<BR><BR>bGreenZero =
FALSE;<BR><BR>}<BR><BR>else<BR><BR>bGreenZero = TRUE;<BR><BR>if
(PaletteColors[i].peBlue >
nDeta)<BR><BR>{<BR><BR>PaletteColors[i].peBlue -=
nDeta;<BR><BR>bBlueZero = FALSE;<BR><BR>}<BR><BR>else if
(PaletteColors[i].peBlue >
1)<BR><BR>{<BR><BR>PaletteColors[i].peBlue--;<BR><BR>bBlueZero =
FALSE;<BR><BR>}<BR><BR>else<BR><BR>bBlueZero =
TRUE;<BR><BR>}<BR><BR>// 如所有颜色分量都为0,则结束渐隐<BR><BR>bDone = bRedZero
&& bGreenZero && bBlueZero;<BR><BR>//
使系统改变调色板<BR><BR>pPal->AnimatePalette(0, nTotalColors,
PaletteColors);<BR><BR>}<BR><BR>::TranslateMessage(&msg);<BR><BR>::DispatchMessage(&msg);<BR><BR>}<BR><BR>}<BR><BR>::ReleaseCapture();<BR><BR>pWnd->KillTimer(0x100);<BR><BR>//
恢复原始调色板<BR><BR>pPal->SetPaletteEntries(0, nTotalColors,
PaletteColors0);<BR><BR>pPal->AnimatePalette(0, nTotalColors,
PaletteColors0);<BR><BR>}<BR></DIV><BR><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR>
<TABLE align=center bgColor=#006699 border=0 cellPadding=0 cellSpacing=0
width=770>
<TBODY>
<TR bgColor=#006699>
<TD align=middle bgColor=#006699 id=white><FONT
color=#ffffff>对该文的评论</FONT></TD>
<TD align=middle>
<SCRIPT src="CSDN_文档中心_用VC 实现图象渐显和渐隐.files/readnum.htm"></SCRIPT>
</TD></TR></TBODY></TABLE>
<TABLE align=center bgColor=#666666 border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TD bgColor=#cccccc colSpan=3><SPAN style="COLOR: #cccccc"><IMG height=16
hspace=1 src="CSDN_文档中心_用VC 实现图象渐显和渐隐.files/ico_pencil.gif" width=16>
</SPAN> artgolf <I>(2000-12-29 17:28:17)</I>
</TD></TR>
<TR>
<TD bgColor=#ffffff colSpan=3
width=532><BR>调色板技术只适合256色位图,对24位或32位真彩色可用OpenGL或Direct3D编程才能保证速度,目前的游戏大多改成了后者。
<BR></TD></TR></TBODY></TABLE><BR>
<DIV align=center>
<TABLE align=center bgColor=#cccccc border=0 cellPadding=2 cellSpacing=1
width=770>
<TBODY>
<TR>
<TH bgColor=#006699 id=white><FONT
color=#ffffff>我要评论</FONT></TH></TR></TBODY></TABLE></DIV>
<DIV align=center>
<TABLE border=0 width=770>
<TBODY>
<TR>
<TD>你没有登陆,无法发表评论。 请先<A
href="http://www.csdn.net/member/login.asp?from=/Develop/read_article.asp?id=2741">登陆</A>
<A
href="http://www.csdn.net/expert/zc.asp">我要注册</A><BR></TD></TR></TBODY></TABLE></DIV><BR>
<HR noShade SIZE=1 width=770>
<TABLE border=0 cellPadding=0 cellSpacing=0 width=500>
<TBODY>
<TR align=middle>
<TD height=10 vAlign=bottom><A
href="http://www.csdn.net/intro/intro.asp?id=2">网站简介</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=5">广告服务</A> - <A
href="http://www.csdn.net/map/map.shtm">网站地图</A> - <A
href="http://www.csdn.net/help/help.asp">帮助信息</A> - <A
href="http://www.csdn.net/intro/intro.asp?id=2">联系方式</A> - <A
href="http://www.csdn.net/english">English</A> </TD>
<TD align=middle rowSpan=3><A
href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG
border=0 height=48 src="CSDN_文档中心_用VC 实现图象渐显和渐隐.files/biaoshi.gif"
width=40></A></TD></TR>
<TR align=middle>
<TD vAlign=top>百联美达美公司 版权所有 京ICP证020026号</TD></TR>
<TR align=middle>
<TD vAlign=top><FONT face=Verdana>Copyright © CSDN.net, Inc. All rights
reserved</FONT></TD></TR>
<TR>
<TD height=15></TD>
<TD></TD></TR></TBODY></TABLE></DIV>
<DIV></DIV><!--内容结束//--><!--结束//--></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -