`
isiqi
  • 浏览: 16489921 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

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

阅读更多
在嵌入式系统下由于嵌入式系统本身资源内存的局限性,导致在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
:最后将计算得到的新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 VisualC ++ 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黄俊峰所写 ,如欲转载 ,请注明出处 。 。 。
分享到:
评论

相关推荐

    嵌入式GIS开发平台eSuperMap介绍

    - **半透明地图渲染**:支持半透明地图渲染效果,增强地图的视觉效果。 - **多边形透明显示**:支持岛洞形状的多边形透明显示,使复杂多边形的显示更加真实。 - **沿线注记显示**:支持快速的沿线注记显示,提高地图...

    多处理器嵌入式软件的全数字仿真测试平台开发技术-刘春龙.pdf

    其优点在于测试透明度高,控制性强,可以方便地注入测试数据,尤其对于那些低概率但安全性至关重要的功能,全数字仿真测试能提供强有力的支持。 在实际应用中,通过这种测试平台,开发者可以更早地发现和修复软件中...

    TFTLCD图片批量取模 + 图标带透明和不带透明取模工具

    这个工具能够创建带有透明通道的图标,透明度可以通过Alpha通道来实现,使得部分图像可以透过,呈现出半透明效果。在嵌入式系统中,透明图标的使用可以提升界面的美观性和用户体验。 另一方面,"不带透明图标制作...

    EVC实现图形显示特技

    还可以通过`setAlpha()`调整透明度,实现半透明效果。 2. **变换矩阵**:通过`translate()`, `rotate()`, `scale()`等方法,可以对图形进行平移、旋转和缩放,从而实现动态效果。 3. **绘图模式**:`setPaintMode...

    分布式分油机仿真面板的设计与实现.pdf

    分布式分油机仿真面板的设计与实现涉及了船舶工程、分布式系统、嵌入式系统设计以及通信协议等多个IT和工程领域的知识。以下为详细的分析与总结: 1. 分布式系统的概念与应用: 分布式系统是一种由多个分散的、通过...

    QT桌面精灵

    2. **透明窗口**:QT支持窗口透明效果,这使得桌面精灵能够以半透明或完全透明的形式出现在桌面之上,不影响用户对底层桌面内容的查看。这种效果是通过设置窗口的alpha通道实现的。 3. **桌面精灵**:桌面精灵通常...

    C#实现的桌面便笺程序

    同时,我们需要考虑窗口的透明度调整,以达到半透明效果,使便笺不遮挡背景窗口的内容。 为了支持多个便笺,我们需要设计一个便笺管理器类,用于创建、保存和加载便笺实例。每个便笺实例应包含文本编辑器控件,用户...

    emWin 5.30

    这对于需要处理半透明图像或者实现复杂视觉效果的应用来说非常重要。通过使用此函数,开发者可以轻松地在不同的层面上应用透明度,而不必担心底层内容被覆盖或丢失。这不仅提高了应用程序的灵活性,还增强了GUI的...

    消除水印神器

    水印通常是在图像上添加的一种半透明或淡化的标识,可以是文字、图案或者logo,其目的是表明图像的所有权或保护版权。在很多情况下,我们需要去除这些水印,以便重新编辑图片或用于商业用途。"消除水印神器"就是为此...

    做好看界面用的Icon Work图标图片处理软件

    4. **透明度调整**:提供直观的透明度滑块,可以调整单个图层或整个图标的透明度,实现半透明效果。 5. **导出与导入**:支持多种图标格式的导入和导出,如ICO、PNG、BMP、SVG等,满足不同平台和应用的需求。 6. **...

    像素操作库pixman

    pixman能确保即使在资源有限的环境下也能实现高质量的图形显示。 3. **服务器端图形**:在X11这样的窗口系统中,pixman用于后台处理像素操作,提升服务器的图形处理能力。 4. **图形编程**:对于开发者来说,...

    行业文档-设计装置-一种带有降温装置的动漫透写桌.zip

    透写桌是动画制作中常用的工具,通过其半透明表面可以让设计师在下面放置参考资料,方便上色和描摹。 在这个主题中,我们可以深入探讨以下几个IT相关的知识点: 1. **硬件设计与集成**:设计这样的装置需要考虑透...

    Embedded graphics on STM32F4 LTDC.pdf

    3. **透明度/Alpha通道**:通过Alpha通道,可以控制图像的透明度,实现半透明效果,使得图像能够与背景或其他层融合。 4. **颜色查找表**(CLUT):CLUT允许将索引颜色映射到实际的RGB值,简化颜色管理,提高处理...

    STM32H750驱动LTDC LCD(RGB屏)【支持STM32H7系列单片机_寄存器库驱动】.zip

    通过调整层的属性,可以实现复杂的显示效果,如图像叠加、半透明效果等。 接下来,我们要关注的是时序控制器(TCON)。LTDC的时序设置涉及到LCD面板的刷新率和像素时钟,这两者对于保证图像无闪烁且清晰至关重要。...

    Pro OpenGL ES for Android

    通过控制像素的不透明度,可以实现实体与半透明物体之间的平滑过渡。在OpenGL ES中,混合技术通常通过设置混合函数来实现,比如使用GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA来控制透明度。 **高级渲染技巧:** 除了...

    基于单片机的投币式全自动豆浆机系统设计.pdf

    7. 系统的自动化和高效率实现:全自动豆浆机系统设计的另一个重点是如何实现设备的全自动化和高效率。通过单片机控制组件将市面上的投币器、电压转换器、水箱和半自动豆浆机进行改进并连接起来,形成一个全新的自动...

    OPENGL ES 3.0编程指南 原书第2版

    7. **混合和颜色逻辑操作**:提供更灵活的像素混合规则,可以实现各种特效,如半透明效果、颜色操作等。 8. **浮点纹理和颜色缓冲**:支持浮点格式的纹理和颜色缓冲,这对于科学可视化、计算着色等领域特别有用。 ...

Global site tag (gtag.js) - Google Analytics