16位Alpha颜色混合(565)

手机上的一些小图标,当按下这些图标时,颜色会发生改变,实现的方式是怎么样的?先看一篇网络上流传的文章:

//------------------------------------------------------------------------------------------------------------------------------------------

16位Alpha混合的简单算法

2008-07-03 20:11:59|  分类: 技术--Alpha混合 阅读25 评论0   字号: 订阅

游戏中,我们常常可以看到一些半透明的图像,那么这些图像是怎么生成的呢?是简单的贴位图做的吗?当然不是,要不美工不就惨死了。这其实是利用程序将两张图片进行混合后的效果,也就是图形的Alpha混合,要得到混合图片,就必须对每个点分别进行处理。让我们来看看如何进行Alpha混合。这里以16位色彩位例子:
  16位色彩下,每个像素都用一个WORD来表示,有16位二进制。这16位,分成三段分别表示像素的R、G、B值。现在的显示卡有两种:555格式的 RGB分别各占5位最高位空、565格式G的值占6位,其他两个分量各占5位。所以首先,我们要得到像素的RGB。

N

R

R

R

R

R

G

G

G

G

G

B

B

B

B

B

 

1 555的RGB分量

 

R

R

R

R

R

G

G

G

G

G

G

B

B

B

B

B

 

2 565的RGB分量


  在DirectDraw下,可以通过锁定表面,得到表面的像素,将他保存到一个WORD*的变量里。当我们得到资源表面和目的表面的像素后,我们就可以开始进行Alpha混合了。16bit的Alpha混合首先必须分别对原和目的表面的像素分色。这可以通过位操作来实现,用像素值分别与RGB对应的特定值进行与操作将多余的其他色去掉,最后通过移位去掉后面的0。这里要注意555显示卡和565显示卡的区别。分色后,混合正式开始,我们将分色得到的R、 G、B的各分色分别混合。下面先看一个公式:A=目的颜色、B=资源颜色、Alpha=混色深度(0 < alpha < 1)

混合后的颜色 = A * Alpha + B * ( 1-Alpha )


  当Alpha=0,混合后的颜色=A。当Alpha=1,混合后的颜色=B。当Alpha介于0与1之间,混合后的颜色包含了资源和目的表面的两种颜色。调整Alpha的值,混合后的颜色就会跟着有规律的变化。但是,颜色是整数,所以,我们必须对公式进行一点简单的变化:

混合后的颜色 = ( A * Alpha + B * ( 32-Alpha ) ) / 32   1 < 32


  这样的等价变化后所有的元素都变成了整数,混合颜色的调整级数为32(更高当然也是可以的,把公式中的32换成其他数,Alpha区值范围也变化),但是计算机处理乘法和除法是很慢的,而Alpha混合是对很多的点进行计算,上面的公式显然是不适合的,我们再来点变化:

混合后的颜色=( ( A-B ) * Alpha ) >> 5 + B


  除以32等于右移5位,这就是调整级数取32的原因。计算机处理移位是很快的。至于那个乘以Alpha,我也不知道有什么简单的方法改成效率更高的算法。分别混合好R、G、B的色后,最后还需要将他们合成,这是个简单的步骤,与分色相反的移位,然后将三个色值按位或操作就可以了。处理了所有需要混色的像素后,记得将表面解锁。

 

转自:http://dev.gameres.com/Program/Visual/2D/Alphajd.htm

//--------------------------------------------------------------------------------------------------------

 

我的项目中的实现代码:

 

void SFUIAWDragView::CreatRedScreen()
 {
  SFUIGraphics uig;
  SFGraphics sfg;

  if (m_pimgRedScreen)
  {
   sf_free(m_pimgRedScreen);
   m_pimgRedScreen=SFNull;
  }
  m_pimgRedScreen=SFImage_CreateOffscreenImage(m_pChildWidget->GetWindowPosition().GetWidth(),m_pChildWidget->GetWindowPosition().GetHeight());
  SFGraphics_CreateFromImage(&sfg, m_pimgRedScreen);
  uig.Attach(&sfg);

  uig.Clear(0xd0d0d0);
  m_pimgRedScreen->iTransparent = RGB_TO_NATIVE(0xd0d0d0);
 
  uig.DrawImage(m_pimgOffScreen,0,0);  //m_pimgOffScreen是点下的图片的IMAGE

  for (int i=0;i<m_pimgRedScreen->iWidth;i++)
  {
   for (int j=0;j<m_pimgRedScreen->iHeight;j++)
   {
    if (((SFNColor*)m_pimgRedScreen->pPixels)[j*m_pimgRedScreen->iWidth+i]==RGB_TO_NATIVE(0xd0d0d0))
     continue;
    else
    {
     int alpha=120;
     SFNColor rsPixel=((SFNColor*)m_pimgRedScreen->pPixels)[j*m_pimgRedScreen->iWidth+i];
    
     SFNColor r=rsPixel&0xF800;
     SFNColor g= rsPixel&0x7e0;
     SFNColor b=rsPixel&0x1f;
     r=((0xf810*alpha+r*(255-alpha))>>8)&0xF800;
     g=(g*(255-alpha)>>8)&0x7e0;
     b=(b*(255-alpha)>>8)&0x1f;
    ((SFNColor*)m_pimgRedScreen->pPixels)[j*m_pimgRedScreen->iWidth+i]=r|g|b;
    
    }
    // ((SFNColor*)m_pimgRedScreen->pPixels)[j*m_pimgRedScreen->iWidth+i]=((SFNColor*)m_pimgRedScreen->pPixels)[j*m_pimgRedScreen->iWidth+i]|RGB_TO_NATIVE(0xff0000);

   }
  }
 }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值