0

I have code below to blend alpha color in ARGB format:

a, b, o are integers, but should always fall in [0x00ffffff,0xffffffff]

o = ( ( ( a >> 24 ) * ( b >> 24 ) ) >> 8 ) << 24;

Is there anyway to optimize it?

Thanks!

echo
  • 789
  • 2
  • 12
  • 21
  • are those > and < supposed to be >> and < – Nick Banks Jan 21 '11 at 22:58
  • there are some mistakes in the question, now they are fixed. thanks. any language is fine. just need some idea to optimize it. :) – echo Jan 21 '11 at 23:05
  • so are you just trying to multiply a and b, and take the upper portion of the multiplication? Also, when you do the final << 24, wouldn't that make all the right digits 0 instead of F? – Nick Banks Jan 21 '11 at 23:11

2 Answers2

1

That doesn't perform the alpha blending. That just combines the alpha component of two pixels. It's also probably about as efficient as you're going to get without going directly to assembly. If you can use pointers, you might get a little faster, though:

byte* pa = (byte*)&a;
byte* pb = (byte*)&b;
byte* po = (byte*)&o;

po[3] = pa[3] * pb[3] >> 8;

This saves most of the shifting. Note that this assumes a little-endian machine. If you're running on a big-endian processor, it becomes even better with:

*po = *pa * *pb >> 8;

In either case, you can turn this into a one-liner by doing all the pointer casting inline, but it gets a bit hard to read.

((byte*)&o)[3] = ((byte*)&a)[3] * ((byte*)&b)[3] >> 8;

or

*((byte*)&o) = *((byte*)&a) * *((byte*)&b) >> 8;
P Daddy
  • 28,912
  • 9
  • 68
  • 92
  • Like I said, there's not much more you can do, although you can save a few clocks with assembly. But still, what makes you think that this code is a bottleneck? Have you profiled? Like I said, this doesn't perform the entire blending operation, and the code for that would be roughly three times this. – P Daddy Jan 22 '11 at 00:21
  • Check that. Six times, actually. – P Daddy Jan 22 '11 at 00:47
  • Great. I just would like to know if there is any trick to improve performance. So considering such inconvenience, why ARGB is commonly used instead of RGBA? – echo Jan 23 '11 at 19:43
0
unsigned int blend(unsigned int a, unsigned int b)
{
  return (((a >> 24) * (b >> 24)) << 16) & 0xFF000000;
}

Is this what you are trying to do? I don't think this is any faster though, but more accuracte according to what you stated.

If you don't need to use bitwise operators you can use pointers too, as shown by other solutions.

Nick Banks
  • 4,298
  • 5
  • 39
  • 65
  • well, I should give an example, though. a=0x01808080, b=0x02808080, o should be 0x02000000. so if you do | 0x00FFFFFF, it is not correct. also << 16 is not equal to >> 24 then << 8. – echo Jan 21 '11 at 23:26
  • Its equal to >> 8 then << 24 though, which is what your code shows. – Nick Banks Jan 21 '11 at 23:33
  • think ( a >> 24 ) * ( b >> 24 ) = 0x2010, >> 8 makes it to 0x20, << 24 makes it to 0x20000000. But << 16 makes it to 0x20100000. – echo Jan 21 '11 at 23:45
  • Then & 0xFF000000 gets rid of all the extra junk – Nick Banks Jan 22 '11 at 00:00
  • So you have actually tried and tested the code above and it already does exactly what you want? If so just that, because there is no way to make that faster with different bitwise operators. In response to your previous comment, in your example of "a=0x01808080, b=0x02808080, o should be 0x02000000" you are getting rid of all the 'junk' after the first 2 hex digits, right? – Nick Banks Jan 22 '11 at 00:46
  • Given `a = 0x01808080, b = 0x02808080`, both your functions result in `0`. One times two doesn't equal 0x2010. It equals 2, which shifted right 8 times equals zero. Neither function includes the R, G, or B channels (what gamernb calls "junk") in the result. – P Daddy Jan 22 '11 at 14:55