How implement alfa channel

Mar 28, 2009 5 Replies

I want to implement a 32 bit bitmap with alfa channel in an arm7 micro....the function is new_pixel=alfa*pixel_foreground+(1-alfa)*pixel_background alfa is an 8 bit value from zero to one (from zero to 255). This function can be done in this way:



1)float cast of alfa and pixel_foreground
2)alfa1=alfa/255
3)new_value1=alfa1*pixel_foreground
3)new_pixel=new_value1+new_value2
3)int cast af new_pixel This procedure is time consuming and very difficult without mathematical coprocessor...any better way? Thanks

Don't use floating point, rearrange the formula so you can use integer arithmetic.

Try this code. It rounds different than your approach because that makes it cheaper to avoid the division by 255, but it's a lot faster.

unsigned int blend_argb32 (unsigned int a, unsigned int b, ui8 delta) { unsigned int dstrb = a & 0xFF00FF; unsigned int dstag = a >> 8 & 0xFF00FF; unsigned int srcrb = b & 0xFF00FF; unsigned int srcag = b >> 8 & 0xFF00FF; unsigned int drb = ((srcrb - dstrb) * delta)>>8; unsigned int dag = ((srcag - dstag) * delta)>>8; a = (drb + dstrb) & 0x00FF00FF; b = (dag + dstag)

If you are representing data as integers there's really no need to convert to floating point to do this. Doing so will rob you of a lot of performance:

pixel = (alpha * foreground + (255 - alpha) * background + 128) / 255;

For most purposes you can drop the + 128. That is only really needed if you are being pedantic - it ensures the division is rounded properly. If the output is a screen you can drop that for a slight speed improvement and you will never notice the difference. It may be needed if the result is used as a further basis for calculation though.

Andrew Smallshaw andrews@sdf.lonestar.org

That divide by 255 can cost you as much time as the rest of the math on that line, make it 256 like everyone else does and double your speed. pixel = ((alpha * foreground + (255 - alpha) * background)) >> 7; You may also need clamping for results not in range of 0-255.

Nah - nowadays all compilers know that division by 2^N, 2^N-1 and 2^N+1 are cheap to calculate. In the case of 255 it becomes:

int DivideBy255 (int a) { return ((a>>8) + a + 1)>>8; }

It could be off one bit if a is negative (haven't checked), but for positive integers it gives identical results.

And before the c-standard nazi chimes in: I assume that signed shifts replicate the sign-bits *and* that a range-propagation pass has made sure that no overflow is possible. This is guaranteed in the case of 8 bit integers.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required