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

STM32 ICO图标解析(支持透明度) 测试环境为STM32F7,支持2个图层,可以支持图层之间显示透明度,测试方法为底层显示背景图标,顶层显示需要显示透明的图标,如果在单个图层显示,需要自己实现alpha混合,混合需要读取之前的像素,与要写入的像素进行混合,混合方法也比较简单可以网上查,或者我的上一篇文章https://blog.youkuaiyun.com/cp1300/article/details/104748720里面有用到像素混合... 阅读详情
在嵌入式系统下,由于嵌入式系统本身资源内存的局限性,导致在Windows下能够轻松实现的功能和效果在嵌入式系统下实现起来却变得非常困难。而且,WinCE下,由于微软为了保证WinCE这个OS操作系统能够足够小,所以减少很多Windows的组件,只保留了OS很核心的一部分。在这种情况下,WinCE操作系统能够缩减到足够小 。但是,微软的这种做法却给我们编程人员带来极大的不便。导致原先我们Windows下信手拈来,随叫随到的API 变的如此陌生,我们不得不另僻曲径,寻找一种替代的方法来实现相同的功能。同时,这也要求我们编程人员对原先不太关心的原理知识做更细致的了解。
   
    
就拿半透明来说,嵌入式下的半透明是困扰很多嵌入式编程人员的难题,就笔者来说,我寻找了大量国内,国外的网站,也咨询过几十位有多年嵌入式方面工作经验的人员,但是没有一个人能够给我良好的解决方案。 目前的实现方法大多数直接写硬件或者直接写显存这样的底层方法来实现。是后来,在笔者自己的努力下,比较完美的在应用层上解决了问题 ,实现高效率的半透明效果。

    
我们先谈谈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
:最后将计算得到的新NewR,NewG,NewB值合成最终的将显示出来的颜色值。
 
     这里需要对半透明区域内所有的像素点都进行如上4步操作,这将涉及到大量的运算。但这并不是最耗时的。最耗时的是获得像素点的颜色值以及设置某个像素点的像素值。即GetPixel()和SetPixel() 。

在WinCE4.2模拟器下做测试,如下一段代码
for(int i = 0 ; i < 100 ; i ++ )
{
for(int n = 0 ; n < 100 ; n ++)
{
pDC->GetPixel(i ,n );
}
}
需要运行4秒钟,即10000次GetPixel操作需要4秒钟,而这只是一块宽100 ,长100的半透明区域而已。

   
所以,最终我们需要用某种替代的方法来代替这个GetPixel和SetPixel函数 。

    在Windows下,可以用GetDIBits和GetBitmapBits来一次性的将所有的像素点读取过来进行分析。
但是在嵌入式下,很不幸,该死的微软把这两个函数给Del掉了,所以,这又必须要求我们寻找另一种替代的方法来实现。在细细的研究了BMP的结构,和DIB设备无关图以后,找到了一种方法来实现半透明的功能,并且在嵌入式系统能够有很高的绘制效率。
 
操作系统: WinCE 4.2 , Emulator  , x86 模拟器。
编程环境: Embedded Visual C ++ , SP4 , StandardSDK
  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黄俊峰所写 ,如欲转载 ,请注明出处 。 。 。
 
lvgl:功能强大且易于使用的嵌入式GUI,具有许多小部件,高级视觉效果(不透明度,抗锯齿,动画)和低内存要求(16K RAM,64K Flash) LVGL-轻便而多功能的图形库 LVGL提供了使用易于使用的图形元素,精美的视觉效果和低内存占用量来创建嵌入式GUI所需的一切。 ···· 产品特点 强大的:按钮,图表,列表,滑块,图像等。 先进的图形:动画,抗锯齿,不透明度,平滑滚动 使用:触摸屏,鼠标,键盘,编码器,按钮等。 使用:例如单色和彩色显示 独立于任何微控制器或显示器使用的硬件 可扩展以使用很少的内存(64 kB闪存,10 kB RAM)进行操作 支持UTF-8的多语言支持,双向和阿拉伯脚本支持 通过完全可自定义的图形元素 支持操作系统,外部存储器和GPU,但不是必需的 即使只有一个也可以平滑渲染 用C语言编写,以实现最大的兼容性(与C ++兼容) Micropython Binding公开了 无需嵌入式硬件即可在PC上开发的 快速开发的和教程 和API参考 要求 基本上,每个现代控制器(能够驱动显示器)都适合运行LVGL。 最低要求是: 名称 最小的 推荐的 建筑 16、32或64位微控制器或处理器 时钟 > 16 MHz > 48兆赫 闪存/ ROM > 64 KB > 180 KB 静态RAM 立即下载

相关推荐

多周期路径及set_multicycle_path详解

默认情况下,每条路径都被定义为单周期,即源触发器在时钟的任一边沿启动(launch)的数据都应该由目的触发器在时钟的下一上升沿捕获(capture)。 有的设计需要在数据被捕获前提供一些额外的周期,这类路径被称为多周期路径。 一、set_multicycle_path命令 命令格式如下: set_multicycle_path .........

Jackiezhang1993的博客 4万+

半透明的实现

uC/GUI系统中的窗体可以实全透明效果,但是无法实现半透明效果。    经过一天的实验,经于实现了窗体的半透明效果,与大家分享   怎么实现半透明效果呢?先考虑原理。   半透明原理:    假设LCD是256色的。颜色格式为332(RGB)    显存中的每一个字节的数据对应一个象素点。    在数据写入显存之前,读取相应相素点值,然后与新的数据按一定

a100501102的专栏 554

告别SquareLine!用免费的NXP GUI-Guider为海思3516AV300开发LVGL界面(附完整移植流程)

本文详细介绍了如何利用免费的NXP GUI-Guider工具为海思Hi3516AV300开发LVGL界面,包括环境配置、代码移植和性能优化等全流程实战指南。特别针对二维码组件缺失等常见问题提供解决方案,帮助开发者零成本构建高效嵌入式GUI系统。

weixin_28292761的博客 415

透明效果算法及程序实现

//#define  TransTimes                    8#define LCDWIDTH  800#define LCDHEIGHT 480#define PIX_BIT   16 /****************************************************************************************//*

nick_TS16949的专栏 1479

5分钟搞定!用Coze+剪映小助手批量生成萌宠视频(附完整工作流配置)

本文详细介绍了如何利用Coze工作流与剪映小助手快速批量生成萌宠视频的完整方案。通过智能内容生成、素材处理、剪辑组装和输出适配四大模块的协同,实现5分钟内完成高质量视频制作。特别适合多宠物账号运营者,工作流支持模板切换和参数修改,大幅提升内容生产效率。

weixin_28678151的博客 389

【福建dem】原始高程数据tif格式

DEM(Digital Elevation Model,数字高程模型)是一种地理信息系统中的关键数据集,它提供了地表地形的三维信息,通常用于分析地貌特征、模拟水文过程、规划建设、灾害预警等多个领域。这种数据对于地理分析非常有价值,例如,它可以用于计算坡度、坡向、地形粗糙度等地形特征,或者进行洪水模拟、地质灾害评估、太阳能辐射分析等。“福建dem原始高程数据tif格式”是研究和理解福建省地形地貌的重要资源,结合GIS工具,可以揭示丰富的地理信息,为科研、工程和决策提供有力支持。

鸿业远图科技 943

STM32驱动ILI9341控制器控制TFTLCD显示

一、用STM32控制TFTLCD显示的编程方法:

liushuiwen101423的专栏 7万+

SWAT模型参数太多搞不定?一篇讲清如何用SWAT-CUP筛选关键敏感参数(含结果图解读)

本文详细解析了如何使用SWAT-CUP进行参数敏感性分析,帮助水文模型初学者从上百个参数中筛选出关键敏感参数。通过实际案例和结果图解读,介绍了敏感性分析的核心价值、SWAT-CUP结果界面解读方法以及参数筛选的四步实战法,显著提升模型调试效率。文章还提供了典型问题排查手册,解决敏感参数与文献不一致、率定后模型变差等常见问题。

weixin_30385925的博客 320

如何开发绚丽、高效率的界面(Windows嵌入式系统)(二)

上篇文章中提到用户体验(UE),并且说到国内有专门去做UE的团队也很少。据我了解Microsoft、Nokia、Google等,还有国内的Baidu是有比较专业的UE团队。对于我们这样的普通团队、普通开发者来说,这样的经验实在太少了。而且普遍更认为UE是UI Designer的事情,与我们这样的Developer没有太多关系。 当然不是,UE远超过UI。很多因素造成了UE差,比如一份不正确的数据...

weixin_33722405的博客 357

AI颠覆市场调研:生成式智能体如何重构商业决策?

AI正在将市场调研从"成本中心"转变为"战略武器"。当企业能够用生成式智能体实时模拟百万级虚拟用户时,传统调研的样本偏差、时间滞后、成本高昂等问题将不复存在。对于开发者而言,这不仅是技术的狂欢,更是参与商业规则重构的历史机遇。行动建议立即体验Simile/Aaru的智能体平台,验证虚拟样本效果参与LLM持续性记忆架构的开源项目(如Memory Llama)关注AI调研API的标准化进程(如Hugging Face的Market Research Toolkit)

这里汇聚了前沿的技术分享与实用的开发技巧,带你探索从创意到企业的技术创业之路。 614

嵌入式Linux图形系统(GUI)介绍

嵌入式Linux图形系统(GUI)介绍    当你在桌面PC上安装Linux时,你通常在很少的几个"标准"的图形支持组件中选择。你很可能使用X Windows系统(XFree86或者Xorg)作为显示界面的基础(与Linux驱动一起来控制硬件),GNOME或者KDE作为桌面环境,浏览器则在FireFox,Konqueror或者Opera等功能全面的几个浏览器中间选择.    但是,这种

kernel_32的专栏 6159

【25届数字IC秋招总结】面试经验10——紫光同芯

25届数字ic面试记录——紫光同芯

lalala0635的博客 862

如何开发绚丽、高效率的界面(Windows嵌入式系统)

原文地址::http://kb.cnblogs.com/page/49641/ 相关网帖 1>ALPHABLEND FOR ARM----http://tctianchi.yo2.cn/articles/alphablend-for-arm.html 上篇文章中提到用户体验(UE),并且说到国内有专门去做UE的团队也很少。据我了解Microsoft、Nokia

xqhrs232的专栏 1101

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

WINCE下实现绚丽的界面技术贴子

1.如何开发绚丽、高效率的界面(Windows嵌入式系统) http://www.evccode.com/bbs/TopicOther.asp?t=5&BoardID=10&id=142 2.M8SDK教程-游戏开发心得(三):DDraw进阶教程-简单贴图,Alpha半透明效果和Sprite动画 http://junelee.spaces.live.com/blog/cns!D0477EE2

xqhrs232的专栏 1850

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

嵌入式linux系统 图像 应用平台,嵌入式Linux图形系统快速参考手册

嵌入式Linux图形系统快速参考手册(Embedded Linux Graphics Quick Reference Guide)译自:http://www.linuxdevices.com/原作者不详当你在桌面PC上安装Linux时,你通常在很少的几个"标准"的图形支持组件中选择。你很可能使用X Windows系统(XFree86或者Xorg)作为显示界面的基础(与Linux驱动一起来控制硬件)...

weixin_33877700的博客 221

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

嵌入式Linux图形系统快速参考手册

嵌入式Linux图形系统快速参考手册(Embedded Linux Graphics Quick Reference Guide)译自:http://www.linuxdevices.com/原作者不详当你在桌面PC上安装Linux时,你通常在很少的几个"标准"的图形支持组件中选择。你很可能使用X Windows系统(XFree86或者Xorg)作为显示界面的基础(与Linux驱动一起来控制硬件)

transistor0的专栏 874

如何开发绚丽、高效率的界面(Windows嵌入式系统)(一)

这篇文章介绍在Windows Embedded CE/Windows Mobile等系统上开发高效的2D应用的技术。文章分为如下几个部分: 1.相关商用产品一览 2.Windows系统下图形编程的相关基础知识 3.DirectDraw简介 4.DirectDraw驱动开发 5.DirectDraw应用开发 6.一个推荐的入门Sample   1.相关商用产品一览 因为嵌入式产品种...

weixin_33958585的博客 235

艾伟_转载:如何开发绚丽、高效率的界面(Windows嵌入式系统)

上篇文章中提到用户体验(UE),并且说到国内有专门去做UE的团队也很少。据我了解Microsoft、Nokia、Google等,还有国内的Baidu是有比较专业的UE团队。对于我们这样的普通团队、普通开发者来说,这样的经验实在太少了。而且普遍更认为UE是UI Designer的事情,与我们这样的Developer没有太多关系。 当然不是,UE远超过UI。很多因素造成了UE差,比如一份不正确的数据表...

weixin_33897722的博客 206
上一篇: WINCE应用的UI实现方案 —— 下篇:代码一小步,项目进度管理一大步
下一篇: 开始→运行→输入的命令集锦
JamesXing
博客等级 码龄20年 30粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值