嵌入式下高效率半透明的实现

原创 2004年12月30日 10:25:00

   在嵌入式系统下 由于嵌入式系统本身资源内存的局限性 ,导致在Windows下能够轻松实现的功能和效果在嵌入式系统下实现起来却变得非常困难 。而且 WinCE 由于微软为了保证WinCE这个OS操作系统能够足够小 所以减少很多Windows的组件 ,只保留了OS很核心的一部分 。在这种情况下 WinCE操作系统能够缩减到足够小  。但是 ,微软的这种做法却给我们编程人员带来极大的不便 导致原先我们Windows下信手拈来 ,随叫随到的API 变的如此陌生 ,我们不得不另僻曲径,寻找一种替代的方法来实现相同的功能 。同时 ,这也要求我们编程人员对原先不太关心的原理知识做更细致的了解 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

   
    
就拿半透明来说 嵌入式下的半透明是困扰很多嵌入式编程人员的难题 ,就笔者来说 ,我寻找了大量国内,国外的网站 ,也咨询过几十位有多年嵌入式方面工作经验的人员 ,但是没有一个人能够给我良好的解决方案 目前的实现方法大多数直接写硬件或者直接写显存这样的底层方法来实现。是后来 ,在笔者自己的努力下 ,比较完美的在应用层上解决了问题 ,实现高效率的半透明效果


    
我们先谈谈window下常规半透明的实现方法


常规半透明的实现方法是 :
 

1: 首先获取目标DC某位置像素点的颜色值 ,将此颜色值拆分为R G B值(假设为R1 , G1 , B1 ,


2:
再获得源DC此位置像素点的颜色值 ,也将此颜色值拆分为R G B值(假设为R2 , G2 , B2


3:
然后将此两颜色的R  , G B值分别按如下公式进行运算

                            
                   New  = Source * Alpha + ( 1 – Alpha) * Dest ;


    分别计算:
   
                   NewR = R1 * Alpha + (1 – Alpha) * R2 ;


                   NewG = G1 * Alpha + (1 – Alpha) * G2 ;

                   NewB = B1 * Alpha + (1 – Alpha) * B2 ;

4
:最后将计算得到的新NewRNewGNewB值合成最终的将显示出来的颜色值

 

     这里需要对半透明区域内所有的像素点都进行如上4步操作 ,这将涉及到大量的运算 。但这并不是最耗时的 最耗时的是获得像素点的颜色值以及设置某个像素点的像素值 。即GetPixel()和SetPixel()

WinCE4.2模拟器下做测试 ,如下一段代码

for(int i = 0 ; i < 100 ; i ++ )

{

for(int n = 0 ; n < 100 ; n ++)

{

pDC->GetPixel(i ,n );

}

}

需要运行4秒钟 ,即10000GetPixel操作需要4秒钟 ,而这只是一块宽100 ,长100的半透明区域而已


   
所以 最终我们需要用某种替代的方法来代替这个GetPixelSetPixel函数

    Windows 可以用GetDIBitsGetBitmapBits来一次性的将所有的像素点读取过来进行分析。

但是在嵌入式下 很不幸 该死的微软把这两个函数给Del掉了 ,所以 这又必须要求我们寻找另一种替代的方法来实现 在细细的研究了BMP的结构 DIB设备无关图以后 ,找到了一种方法来实现半透明的功能 ,并且在嵌入式系统能够有很高的绘制效率

 

操作系统: WinCE 4.2 Emulator  , x86 模拟器

编程环境: Embedded Visual  C ++  SP4  StandardSDK


/*-------------------------------------------------------------
  2004-12-1  Ricky 黄俊峰 编写  
  Function:   在显示DC上画一块半透明区域
  In:

  CDC              *pDstDC      目标DC
  CRect              rtTran          在目标DC上的半透明区域
  COLORREF   clrSrc          与目标区域进行Alpha混和的颜色
 
 需要优化的地方
 1:  传入透明度做为参数
        这里半透明运算 ,没有用常规的拆分法来做 , 为了加快速度 , 将浮点运算改成了移位运算
        为了方便 ,这里统一显示的是50%透明度的半透明效果
       实际想改成任意透明度的话 ,也是非常方便的。详细修改方法 ,请查看我的另一篇关于Alpha
       混和的文章。
2: 用RGBQUAD* pRgb 代替 BYTE *pbtPixel ; 一次进行多个数值的运算 。
3: 嵌入MMX汇编指令 ,加快运算速度 。

     ------------------------­--­--­--­--­------------------------------*/
void DrawSemiTransparentRect(CDC *pDstDC, CRect rtTran, COLORREF clrSrc)
{
        int nSavedDC = pDstDC->SaveDC();                                        //保存原始DC


        int nWidth   = rtTran.Width();                                                     //半透明区域的宽度
        int nHeight  = rtTran.Height();                                                     //半透明区域的高度

       
        //拷屏 , 新建一个DC来拷贝目标区域
        CDC  bmpDC;                                                            
        bmpDC.CreateCompatibleDC(pDstDC);
        CBitmap  bmp ;
        bmp.CreateCompatibleBitmap(pDstDC , nWidth , nHeight);
        CBitmap* pOldBmp = (CBitmap*)bmpDC.SelectObject(&bmp);
        bmpDC.BitBlt(0 , 0 , nWidth , nHeight , pDstDC , rtTran.left , rtTran.top , SRCCOPY);


        //获取bmpDC中的图形数据到BYTE数组
        HDC hDIBDC = CreateCompatibleDC(NULL);

        BITMAPINFO hdr; 
        ZeroMemory(&hdr , sizeof(BITMAPINFO));

        hdr.bmiHeader.biSize         =  sizeof(BITMAPINFOHEADER);
        hdr.bmiHeader.biWidth      =  nWidth;
        hdr.bmiHeader.biHeight     =  nHeight;
        hdr.bmiHeader.biPlanes     =  1;
        hdr.bmiHeader.biBitCount =  32;        /* 这里统一用32位图形 ,原因是32位图形结构相对固定 , 每个
                                                                            像素用4个字节表示 。每行末尾不需要添加额外的字节。
                                                                      而24位图形 , 每行末尾需要添加额外的字节 , 以保证每行的
                                                                            字节数是4的整数倍
                                                                      如果想缩减开销和字节数 , 可以采用24位的图形 ,不过就会多
                                                                               出一些判断添加额外自己的代码 。*/

        BYTE * pbtPixels = NULL ; 

        HBITMAP hDIBitmap  =  CreateDIBSection(hDIBDC, 
                                                                     (BITMAPINFO *)&hdr, 
                                                                     DIB_RGB_COLORS,
                                                                     (void **)&pbtPixels, 
                                                                     NULL, 
                                                                     0);

       HBITMAP hOldBmp = (HBITMAP)SelectObject(hDIBDC, hDIBitmap);
       BitBlt(hDIBDC,0,0,nWidth,nHeight,bmpDC,0,0,SRCCOPY);
       SelectObject(hDIBDC, hOldBmp);

     
      //对BYTE数组进行Alpha混和
       int nPixelSize = 4 ;                                                    //每个像素点用4个字节来存储

       BYTE btSR = GetRValue(clrSrc);
       BYTE btSG = GetGValue(clrSrc);
       BYTE btSB = GetBValue(clrSrc);

       for(int i = 0 ; i < nHeight ; i ++)
      {
             for(int j = 0 ;  j < nWidth ; j ++)
            {
   
                       BYTE btB = pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize  ] ;
                       BYTE btG = pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize + 1 ] ;
                       BYTE btR = pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize + 2 ] ;

                       btB = (btSB + btB ) >> 1 ; //btB = btSB * 0.5 + (1-0.5) * btB;
                       btG = (btSG + btG ) >> 1 ; //btG = btSG * 0.5 + (1-0.5) * btG;
                       btR = (btSR + btR ) >> 1 ; //btR = btSR * 0.5 + (1-0.5) * btR;
   

                       pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize  ]     = btB ;  
                       pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize + 1 ] = btG ;
                       pbtPixels[i *  nWidth * nPixelSize   + j * nPixelSize + 2 ] = btR ;

             }
        }

 

        //绘制最终半透明图形到目标区域
 
        SetDIBitsToDevice(pDstDC->GetSafeHdc(),
                                       rtTran.left,
                                       rtTran.top,
                                       nWidth,
                                       nHeight,
                                       0,
                                       0,
                                       0,
                                       nHeight,
                                       (void*)pbtPixels,
                                       (BITMAPINFO*)&hdr,
                                       DIB_RGB_COLORS);


           //析构和清空
           bmpDC.SelectObject(pOldBmp);
           bmp.Detach();
           delete [] pbtPixels ;
           DeleteObject(hDIBDC);
           pDstDC->RestoreDC(nSavedDC);                                                         //恢复初始DC
}

上面所有代码为Ricky黄俊峰所写 ,如欲转载 ,请注明出处 。 。 。

[MFC] 几种子控件半透明效果的实现办法

什么是 ? 如下图所示 美图秀秀中间的四个按钮 边缘都有椭圆效果: 熟悉MFC开发的都知道 虽然四个按钮的边缘是椭圆的 实际上椭圆之外的角落里 也属于子控件的窗口区域  即:如下图所示 虽然子控件...
  • felicityWSH
  • felicityWSH
  • 2017年03月30日 15:55
  • 624

轻松实现部分背景半透明的呈现效果

实现一个简单的呈现/解散动画效果,当呈现时,呈现的主要内容和背景要明显区分,背景呈现一个半透明遮罩效果,透过背景可以看到下层 View Controller 的内容...
  • kmyhy
  • kmyhy
  • 2016年11月24日 17:16
  • 3176

【转】C#实现Winform自定义半透明遮罩层

转自:http://www.cnblogs.com/JuneZhang/archive/2012/07/06/2579215.html 在网页中通过div+css实现半透明效果不难,今天我们...
  • zjwen2007
  • zjwen2007
  • 2014年11月26日 10:00
  • 609

jquery 半透明遮罩效果

首先谈谈最简单的实现方式吧。准备两个div,一个是幕布,另一个是要显示在屏幕正中央的部件,content 里面要显示什么东东,就由你自己去定义了。可以是图片,也可以是图表、视频什么的。然后就是添加效果...
  • zheng963
  • zheng963
  • 2015年04月16日 18:07
  • 1398

半透明的实现

uC/GUI系统中的窗体可以实全透明效果,但是无法实现半透明效果。    经过一天的实验,经于实现了窗体的半透明效果,与大家分享   怎么实现半透明效果呢?先考虑原理。   半...
  • a100501102
  • a100501102
  • 2015年02月27日 12:16
  • 146

android半透明引导页

这里只是一个简单的demo,先看效果图,第一张图片中,背景是半透明的,在Button位置是全透明,点击任意位置后,该引导页消失,用户看到第二张图片的内容,开始使用APP。...
  • u010060960
  • u010060960
  • 2016年05月16日 23:40
  • 3989

扩展系统功能——装饰模式(四):透明与半透明装饰模式,装饰模式注意事项,装饰模式总结

12.4 透明装饰模式与半透明装饰模式       装饰模式虽好,但存在一个问题。如果客户端希望单独调用具体装饰类新增的方法,而不想通过抽象构件中声明的方法来调用新增方法时将遇到一些麻烦,我们通过一...
  • Mark_LQ
  • Mark_LQ
  • 2015年09月13日 12:10
  • 1061

半透明子窗体MFC实现

上一篇说了大概的思路,但是写的时候就可能遇到各种问题,下面给出完整的步骤源代码。 先建立一个MFC的对话框程序,然后添加类CTransparentWnd,以下给出改动后的代码。 1、CTranspar...
  • xqyphp
  • xqyphp
  • 2015年03月06日 09:55
  • 693

Android半透明+RGB颜色代码大全

半透明值: 不透明 100% FF   95% F2   90% E6   85% D9   80% CC   ...
  • Memories_Code
  • Memories_Code
  • 2017年05月31日 17:06
  • 5683

Android 设置透明、半透明等效果

设置透明效果 大概有三种1、用android系统的透明效果 Java代码 android:background="@android:color/transparent" 例如 设置按钮 Java代...
  • qq_26981913
  • qq_26981913
  • 2016年10月18日 10:00
  • 2023
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式下高效率半透明的实现
举报原因:
原因补充:

(最多只允许输入30个字)