alpha add运算优化

这不是一个新的算法或者思路,如果搜索的话,会看到很多的,这个算法只是可以将尽可能的方便CPU的计算而已。

先看代码,这是ALPHA的优化算法(颜色格式:R5G6B5,Alpha最大值31):

       #define DRAW_OP_ALPHA_565(SRC, DES, ALPHA)                              \
        {                                                               \
                uint32 front =((uint32)(SRC)|((uint32)(SRC)<<16))&0x07E0F81F; \
                uint32 back =((uint32)(DES)|((uint32)(DES)<<16))&0x07E0F81F; \
                uint32 result =((((front-back)*ALPHA)>>5)+back)&0x07E0F81F; \
                DES = (uint16)(result|result>>16);                      \
        }

       

上述运算只是将数值由16位扩展到32位,然后进行统一的计算,对于R5G6B5的颜色的二进制表示:RRRRRGGGGGGBBBBB,调整为:00000GGGGGG00000RRRRR000000BBBBB

对于alpha add的计算,由于增加了上限的判断,及当颜色分量大于最大值的时候,要按最大值来进行计算,于是就进行了下面的修改:

       #define DRAW_OP_ADD_565(SRC, DES, ALPHA)                                \
        {                                                               \
                uint32 front =((uint32)(SRC)|((uint32)(SRC)<<16))&0x07E0F81F; \
                uint32 back =((uint32)(DES)|((uint32)(DES)<<16))&0x07E0F81F; \
                uint32 result =(((((front)*ALPHA)>>5)&0x07E0F81F)+back); \
                if (result & (1<<27))                                   \
                        result |=0x7E00000;                             \
                if (result & (1<<16))                                   \
                        result |=0x0FC00;                               \
                if (result & (1<<5))                                    \
                        result |=0x1F;                                  \
                result &=0x07E0F81F;                                    \
                DES = (uint16)(result|(result>>16));                    \
        }
       

相比于alpha运算,在arm的CPU上,大约增加了6条指令,考虑到arm的CPU上的指令均支持条件执行,因此,对于执行周期来说,估计可能增加4个左右的周期,相对来说,还是可以接受的。

对于alpha sub的运算,也可按照类似的优化步骤。如果谁有更好的优化方法的话,希望可以告诉我。当然,为了大部分人可以看懂,不太欢迎汇编形式

快速16位色alpha运算

很早之前看到别人写的24位色快速alpha运算,那个时候在做symbian,就按照算法写了一个12位色的快速alpha运算。前些年开始做BREW,又写了个16位色的alpha运算,经过不少项目的测试,在效率和效果上完全可以达到应用的要求。在BREW上执行的非常快。

       uint32 front = (((uint32)(*psrc)) & 0xF81F) | (( ((uint32)(*psrc)) & (~( 0xF81F )) ) < < 16);
       uint32 back = (((uint32)(*pdes)) & 0xF81F) | (( ((uint32)(*pdes)) & (~(0xF81F)) ) << 16);
	   uint32 result = ( ( back << 5 ) + ( front - back ) * alpha ) >> 5;
	   *pdes = ( uint16 )((result & 0xF81F) | ( ( (result>>16) & (~(0xF81F ) ) ) ) );
       

alpha的范围在0~31之间。颜色格式为R5G6B5。使用一次乘法。