r = (a * r) >> 8;
g = (a * g) >> 8;
b = (a * b) >> 8;
Ouch - No.
255 * 255 / 256 = 254
Even rounding won't fix that mistake.
When you multiply 8 bit components, you have to divide by 255.
Fortunately, there are some tricks to do that without using an actual
divide.
Wow, did I ever get hammered on that little "optimization". For those
watching at home, the optimization Chris is talking about is probably
this one:
tmp = alpha * red;
remainder256 = tmp & 0xFF; // get alpha * red (mod 256)
dividend = tmp >> 8; // compute alpha * red / 256
remainder255 = dividend + remainder256; // compute alpha * red (mod 255)
dividend += ((remainder255 >= (255 + 128)) & 1) + ((remainder255 >=
128) & 1); // add 0, 1, 2 depending on how large the remainder (mod
255) is
This is provably correct and even rounds correctly. And yes, it would
be much, much easier in AltiVec.
Note that the right shift by 8 is an approximation to dividing by
255, but it shouldn't make that much difference.
I hope you don't ship applications that do that.
And you still should use rounding.
Chris
Well, most of my applications are effectively in-house and are geared
toward speed at the expense of a little slop (since most of the data I
process is very repetitive and not really meant to be agonized over by
human beings). If I had known that everyone on this list takes their
divisions so seriously, I might have spent the time to do it right the
first time. :-)