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

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 立即下载

相关推荐

STM32F407 步进电机S形曲线加减速

步进电机

smallerlang的博客 1591

半透明的实现

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

a100501102的专栏 554

智能车学习日记【二】————十字和斜入十字

智能车学习日记【二】————十字和斜入十字 文章目录 智能车学习日记【二】————十字和斜入十字 前言 一、普通十字补线 二、斜入十字 1.判断是否为斜入十字和斜入十字类型 2.找斜入十字拐点 总结 前言 经过了一个多月的学习,小白的我终于也是能较稳定调出了2.8m以上的四轮车,过程中也遇到了很多困难,其中就有十字补线和斜入十字补线。尤其是斜入十字也是困扰了我快一周,现在和大家分享一下我处理斜入十字的方法(我的方法其实还有很多漏洞需要改进,仅供大家参考理解一下,欢迎各位在评论区指点出可

bsefef的博客 2740

透明效果算法及程序实现

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

nick_TS16949的专栏 1479

VirtualBox创建虚拟机(为安装Ubuntu桌面系统)

Ubuntu的安装非常灵活。但是万变不离其宗,归纳起来,无非就是以下3种:(1)用户可以下载完整的ISO镜像文件,将其转移到各种介质上面,例如DVD或者U盘,然后以该介质引导系统进行安装。(2)用户可以下载一个非常小的网络安装器,利用该安装器引导系统进行在线安装。(3)用户可以将Ubuntu安装到一个U盘中,随身携带。为了便于读者学习,本节将介绍通过完整的ISO镜像文件安装Ubuntu。其他的安装方式将在后面介绍。

夏天又到了的专栏 2687

多模型机器学习生存预测分析:AUC比较、生存分层与SHAP解释

本文研究了多种机器学习模型在心力衰竭患者生存预测中的应用。通过比较逻辑回归、随机森林、XGBoost、LightGBM和梯度提升机五种模型的AUC表现,选择最优预测模型。基于最优模型的预测概率对患者进行风险分层,并使用Kaplan-Meier生存分析和log-rank检验验证分层的有效性。最后采用SHAP方法解释模型决策过程,识别关键预测因素。研究提供了从模型构建、评估到解释的完整技术流程,为临床预后预测提供了可复现的分析框架。

AI的内部世界的博客 157

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

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

liushuiwen101423的专栏 7万+

图神经网络实战——总结 | 图神经网络展望

短短数年时间,图神经网络 (Graph Neural Networks, GNN) 已经成为一种重要的深度学习架构,并且已经广泛应用于各个行业。通过本专栏的学习,能够对图学习和 GNN 领域有一个全面的了解,并能为各种应用设计、构建GNN模型。

盼小辉丶的博客 8541

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

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

weixin_33722405的博客 357

全覆盖路径规划开源项目Clean-robot-turtlebot3关键函数解析(上)

本系列文章主要介绍全覆盖路径规划开源项目Clean-robot-turtlebot3的相关内容,包含如下四篇文章,分别介绍了开源项目Clean-robot-turtlebot3流程的概括总结、ROS坐标系常用坐标及其变换、Clean-robot-turtlebot3关键函数解析等内容。

慕羽★的博客 2778

Python 爬虫教程:金融数据定向抓取(银行 + 投资网站数据结构化提取)

在当今数字化时代,金融数据的获取和分析对于投资者、分析师以及金融机构来说至关重要。Python 爬虫技术可以帮助我们高效地从各种网站上抓取金融数据,从而为投资决策、风险评估和市场分析提供支持。本文将详细介绍如何使用 Python 爬虫技术来定向抓取银行和投资网站的数据,并将其结构化提取,以便进一步分析和使用。

u014481728的博客 881

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

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

kernel_32的专栏 6159

uniapp [全端兼容] - 实现内网使用天地图离线地图,详解项目加载天地图的离线地图服务器部署与使用教程示例源码,Uniapp如何实现天地图的离线加载部署在内网访问(兼容H5、微信小程序、App)

uniapp天地图如何离线访问,无需网络调用天地图API,天地图离线地图,天地图——内网使用离线地图,uniapp中加载天地图的离线地图,uniAPP实现天地图离线访问,在内网中无法直接使用外网天地图资源怎么办,在uni-app中加载地图 -使用天地图的瓦片数据。UNIAPP天地图离线怎么使用,内网部署天地图,天地图离线瓦片,部分瓦片数据,天地图如何离线,下载天地图离线服务,并用Uniapp+天地图离线部署,天地图私有化部署,实现离线加载天地图,Java+uniapp天地图离线开发,uniapp项目中无网络

🏆 前端领域优质创作者 4900

如何开发绚丽、高效率的界面(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

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

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

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

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

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

weixin_33877700的博客 221

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

嵌入式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、付费专栏及课程。

余额充值