首页 > 编程知识 正文

算法是什么(ai晶格化)

时间:2023-05-05 01:39:07 阅读:74638 作者:163

最近的战斗机正在研究透明框显示在TQ2440 4.3英寸屏幕上的透明框问题这一阿尔法混合算法。 几个周转的总结如下

混合算法目前常用的算法是AlphaBlend。 alpha -混合实际上是根据“alpha”混合向量的值混合源像素和目标像素。 alpha混合技术:渲染包含alpha通道值的图形称为alpha混合技术。 渲染意味着在目标设备上绘制包含alpha通道值的像素。 目标设备原本就有背景色或背景图像,目标设备可以是真实的显示器,也可以是内存中的逻辑屏幕。

计算公式如下。 假定一个图像是a,另一个透明图像是b,则当通过b观看a时,所看到的图像c是b和a的混合图像。 b图像的透明度为alpha (值为0-1,1为完全透明,0为完全不透明)。 阿尔法混合式如下。

r(c )=(1-阿尔法) r ) b )阿尔法(r ) a ) )

g(c )=(1- alpha ) ) g ) b ) alpha (g ) a ) ) ) ) )。

b(c )=(1-阿尔法) b ) b )阿尔法(b ) a ) )

r(x )、g )、b ) ) x )分别是指颜色RGB成分原色值. 从上面的公式可以看出,阿尔法实际上是决定混合透明度的数值。 改变这个阿尔法值可以得到渐变的效果。 分离RGB颜色并以"位和"、"移位"进行运算方法; 的比例按2的n次方进行排名。 这样,可以高速运算。 如果32级阿尔法=n/32、b图权重=(32-n )/32,则a图的权重=n/32,得到这样的算法:

r(c )=(32-n ) r ) b ) n*r ) a;

再将r(c )向右移动5位(除以32 )即可

具体算法如下:1)首先分离源像素和目标像素的RGB三个颜色分量。 2 )然后,将原始像素的三个颜色分量分别乘以alpha值,并将目标像素的三个颜色分量分别乘以alpha值的反数值。 3 )将结果按对应的颜色成分相加。 4 )最后求出的每个成分的结果除以alpha的最大值(alpha值,16位颜色的颜色深度为32级,因此alpha取值0-32,因此向右移动5位,编译器的处理位移远快于除法运算)。 5 )最后将3个颜色成分再合成为1个像素并输出。

在程序中,首先读取某个点的值。 这可以参考天嵌的印刷点函数,反向读取与某个点对应的像素。 程序为读数c=LCD_BUFFER[(y ) ][(x ) ]; 读取后,对象是数据的分离,公式src2=((src16 )|src )0x07E0F81F; 将目标像素转换为32个像素,将像素格式从R:G:B改变为G:R:B格式,以同样的方式对源像素进行处理,将源图像乘以alpha诚实,将目标图像乘以相反的值,并且将两个图像分量相加alpha (1- alpha dsha ) ) dsha alpha最大值32变为dst2=src2* alpha (32-alpha ) *dst2/32,变形为dst2=(src2-dst2) alpha 恢复为16位数据格式时,此dst2是透明边框的像素点。 通过依次变换想要实现的透明框的像素点,可以实现透明框。 从上面的流程可以看出,alpha值越大,透明效果越弱。 阿尔法值达到最大时会变得不透明。 相反,阿尔法值为0时。 完全透明。

快速ALPHA BLENDIN算法

//src:源颜色//dst:目标颜色//alpha :透明度(0到32 ) /返回值:混合颜色。

u16GUI_alpha_blend565(u16src、u16 dst、u8 alpha )。

{

u32 src2;

u32 dst2;

SRC2=(src16 )|src )0x07E0F81F;

DST2=(dst16 )|dst )0x07E0F81F;

//dst2=() ) (dst2-src2)阿尔法)5) src2)0x07E0F81F;

dst2() (src2-dst2)阿尔法)5) dst2)0x07E0F81F

返回(dst 216 )|dst2;

}

p>

int GetPixel(U32 x, U32 y)  //读取原图像素点 由上面的函数改编过来

{

    U32 c;

    if((x < SCR_XSIZE_TFT) && (y < SCR_YSIZE_TFT))

        c = LCD_BUFFER[(y)][(x)];

    return c;

}

//x,y,width,height:区域设置//color:alphablend的颜色//aval:透明度(0~32)

void gui_alphablend_area(U16x,U16 y,U16 width,U16 height,U16 color,U8 aval)

{

    U16 i,j;

    U16 tempcolor;

    for(i=0;i<width;i++)

    {

        for(j=0;j<height;j++)

        {

            tempcolor=GetPixel(x+i, y+j);

            tempcolor=gui_alpha_blend565(tempcolor,color,aval);

            PutPixel(x+i,y+j,tempcolor);

        }

    }

}


在这里透过B去看A,或者透过A去看B,其实无非不过区别就是alpha的正值和alpha反值区别。程序的体现就在于

dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;

    dst2=((((src2-dst2)*alpha)>>5)+ dst2)&0x07E0F81F;

最终效果都一样能实现透明框算法。无非不过 透明度取值问题。


64K 色模式下的快速 Alpha混合算法

在 32/64k 色模式下,由于每个点的 RGB 值是放在一个字里,以 16bit 色为例, 一般是按 RGB 或 BGR 565 存放. 传统的软件 Alpha 混合算法是先将 RGB 分离出来, 分开运算,然后再合成. 这造成了 16bit 模式下的 alpha 混合比 24bit 模式下慢 的现象,但使用 16bitcolor 真的那么慢吗? 我认为如果不使用 MMX 指令, 15/16 的比 24bit 的快. 因为我们可以使用一个小的技巧来同时计算 RGB. 而 24 bit 颜色,除非使用 MMX 指令,否则必须分开计算 R G B.

先设 color 是 RGB 565 的, 那么按 2 进制看, 这个颜色字是这样分布的:

RRRRR     GGGGGG   BBBBB

5位                    6位           5位

而 386 以上 CPU 都有 32 位的寄存器,我们只需要将 16bit RGB 变形为

00000       GGGGGG 00000       RRRRR     000000     BBBBB

5位                    6位 5位        5位           6位           5位

储存在 32 位寄存器中,(就是把绿色提到前 16 位里) 由于64k 色下颜色深度是 32 级的,所以 alpha 也只用分 32 级就能满足需要. 那么对上面变形过的双字处理,可以同时算 RGB 了. (Color1*Alpha+Color2*(32-Alpha))/32 能不能简化为(Color1-Color2)*Alpha/32+Color2.? 我思考过这个问题,以为减法将产生负数,这样再算乘法时有可能出问题,但是经过测试,这样简化似乎又没有问题. 毕竟极小的误差是可以忽略的

来源一:http://blog.csdn.net/xhhjin/article/details/6445460

 

alpha混合其实很简单,要做的只是分解源颜色c1,目的颜色c2,然后将颜色分量r1,g1,b1和r2,g2,b2分别按照公式(clr*alpha+clr*(32-alpha))/32来计算,最后再组合成一个颜色值即可,可是如此计算,运算量很大速度很慢。 所以现在就要用到一个技巧,首先,就16位色来说一般的格式是565,表示rgb分量的二进制位数,如图1。 那么我们就可以利用一个32位的变量来把这个颜色的绿色分量提前,变为如图2的格式。这样每个颜色分量中间就有了进位的空间,也就不用分解这个颜色值了。然后,将变形完的两个颜色值按照上面公式进行计算,计算完毕再变回565的格式就完成了一次alpha混合的计算。 

c语言源代码如下:

__inline void MakeAlpha(WORD* wpSrc, WORD* wpDes, WORD wAlpha)
{
   register DWORD d1; // 计算用的中间变量,声明为寄存器变量快些
   register WORD wa = *wpSrc; // 源颜色 
   register WORD wb = *wpDes; // 目的颜色
   register DWORD alpha = wAlpha; // alpha值,16位色的色深为32级,故alpha取值0-32
// (c1-c2)*alpha/32+c2 由(c1*alpha+c2*(32-alpha))/32变形

// 而来,减少了一次乘法运算
// 下面的式子故意写成这样,编译器会把它处理的很好
// 要比这样快一些
// c1 = (((wa << 16) | wa) & 0x7e0f81f);

// 16位变形32位 0x7e...f为二进制的00000111111000001111100000011111
// c2 = (((wb << 16) | wb) & 0x7e0f81f); 
// d1 = ((c1-c2)*alpha)>>5+c2;

// 除以32等于右移5位,但是位移操作要比乘除法快的多,

// 例如:a*320可以写成a*256+a*64=>(a<<8)+(a<<6)

   d1 = (((((((wa << 16) | wa) & 0x7e0f81f) - (((wb << 16) | wb) & 0x7e0f81f)) * alpha) >> 5) + (((wb << 16) | wb) &0x7e0f81f)) & 0x7e0f81f;
        wa = (d1 & 0xffff0000)>>16; // g...r...b => ..g..
        wb = d1 & 0xffff; // g...r...b => r...b
        *wpDes = wa | wb; // rgb
}

来源二:http://blog.chinaunix.net/uid-8272118-id-2033330.html


w_201505于百叶路

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。