How implement alfa channel

D

doc.bullwinkle

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
 
O

overview

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

I think it may be better if you use:
new_pixel=alfa*(pixel_foreground-pixel_background)+pixel_background
only one '*' operation is needed
 
B

Bartc

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?

This sounds like it will be slow even using integer arithmetic: you need to
fetch the foreground and background 24-bit colour values, and calculate
8-bits at a time for each.

What are the sources of the foreground, background and alpha images? What is
the destination? Can you overwrite any source images?

If this is for display, is there any hardware assistance available? If not,
try the C code suggested, but you might end up needing some assembler to
efficiently deal with rows of pixels.

And if multiply is inefficient on your processor, you might try
multiplication using a look-up table. The division should reduce to a
right-shift.

And in any case, try google for "fast alpha blending" for other ideas.
 
E

Eric Sosman

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?

On the assumption that you will push a large number of
pixels through this calculation while keeping `alfa' fixed,
have you considered pre-computing a 256-place lookup table?
To reduce truncation errors you'd probably want to fill the
table with scaled values of, say, 16 bits, and then scale
down after the addition:

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = (alfa << 8) * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + table[256-p.bg]) >> 8;

Optional refinement: Round the sum before right-shifting.
 
P

Phil Carmody

Richard Heathfield said:
overview said:


alfa is 255 - all foreground, please - no background.

You've asked for 255 portions of foreground, and -254 portions
of background. It fails equally with the original equation.
Overview's reformulation isn't what broke it.
Sorry, but it just doesn't work.

It would do if alfa is in [0, 1]. The OP's definition of terms was
flawed. He should have used alfa1 (=alfa/255) rather than alfa
in the above.

Phil
 
B

Ben Bacarisse

Eric Sosman said:
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?

On the assumption that you will push a large number of
pixels through this calculation while keeping `alfa' fixed,
have you considered pre-computing a 256-place lookup table?
To reduce truncation errors you'd probably want to fill the
table with scaled values of, say, 16 bits, and then scale
down after the addition:

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = (alfa << 8) * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + table[256-p.bg]) >> 8;


I think you meant 255-p.bg here. If not, the table size should be one
bigger.

I don't get this code at all. Why multiply alpha by 256? For one
thing, (alpha << 8) * i will often "wrap round". That can't be right,
surely?

Also I can't see the connection between table[256-p.bg] and
multiplying by 1-a (or 255-alpha if in the integer version).

I think this works (modulo rounding):

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = alfa * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + (bg said:
Optional refinement: Round the sum before right-shifting.
 
E

Eric Sosman

Ben said:
Eric Sosman said:
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?
On the assumption that you will push a large number of
pixels through this calculation while keeping `alfa' fixed,
have you considered pre-computing a 256-place lookup table?
To reduce truncation errors you'd probably want to fill the
table with scaled values of, say, 16 bits, and then scale
down after the addition:

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = (alfa << 8) * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + table[256-p.bg]) >> 8;


I think you meant 255-p.bg here. If not, the table size should be one
bigger.


Right you are: I thinko'ed my way into an off-by-one error.
I don't get this code at all. Why multiply alpha by 256? For one
thing, (alpha << 8) * i will often "wrap round". That can't be right,
surely?

Yet another thinko on my part: The O.P. describes alfa as
a "value from zero to one," but goes on to explain that it's
encoded as "from zero to 255." In other words, alfa is already
scaled and my sketch scales it yet again.
Also I can't see the connection between table[256-p.bg] and
multiplying by 1-a (or 255-alpha if in the integer version).

Consider the alfa value 42/255, encoded as 42. The
value 1-alfa is then 1-42/255 = (255-42)/255, encoded as
255-42 (after fixing my off-by-one error).
I think this works (modulo rounding):

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = alfa * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + (bg << 8) - table[p.bg]) >> 8;


Here we've either committed the same thinko, or perhaps
I've tricked you into sharing mine. The final line should be

new_p = (table[p.fg] + table[255-p.bg]) >> 1;

.... because (as noted earlier) the scaling is as I suggested.

Some days it just doesn't pay to get out of bed ...
 
B

Ben Bacarisse

Eric Sosman said:
Ben said:
Eric Sosman said:
(e-mail address removed) wrote:
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?
On the assumption that you will push a large number of
pixels through this calculation while keeping `alfa' fixed,
have you considered pre-computing a 256-place lookup table?
To reduce truncation errors you'd probably want to fill the
table with scaled values of, say, 16 bits, and then scale
down after the addition:

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = (alfa << 8) * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + table[256-p.bg]) >> 8;


I think you meant 255-p.bg here. If not, the table size should be one
bigger.


Right you are: I thinko'ed my way into an off-by-one error.
I don't get this code at all. Why multiply alpha by 256? For one
thing, (alpha << 8) * i will often "wrap round". That can't be right,
surely?

Yet another thinko on my part: The O.P. describes alfa as
a "value from zero to one," but goes on to explain that it's
encoded as "from zero to 255." In other words, alfa is already
scaled and my sketch scales it yet again.
Also I can't see the connection between table[256-p.bg] and
multiplying by 1-a (or 255-alpha if in the integer version).

Consider the alfa value 42/255, encoded as 42. The
value 1-alfa is then 1-42/255 = (255-42)/255, encoded as
255-42 (after fixing my off-by-one error).


No, still don't get it. I know the table[max-val] pattern, but it is
for complementing the multiplicand not the multiplier (and these are
not commutative, of course). See below.
I think this works (modulo rounding):

unsigned short table[256];
for (i = 0; i < 256; ++i)
table = alfa * i;
for ( ... each pixel p ... )
new_p = (table[p.fg] + (bg << 8) - table[p.bg]) >> 8;


Here we've either committed the same thinko, or perhaps
I've tricked you into sharing mine.


Let's do a worked example. alpha=42, fg=10, bg=20. Do you agree that
the answer we want is 10 * 42/255.0 + 20 * 213/255.0 = 18 (and a bit)?
If I've got the basic objective wrong then all bets are off, but that
seems to me what we are trying to do.

My code gives:

(table[10] + (20 << 8) - table[20]) >> 8

table[10] is 42*10 = 420, table[20] is 42*20 = 840, 20<<8 is 5120 so I
get

(420 + 5120 - 840) >> 8 == (4700 >> 8) == 18 (and a bit). Yes?
... The final line should be

new_p = (table[p.fg] + table[255-p.bg]) >> 1;

... because (as noted earlier) the scaling is as I suggested.

yours gives

(table[10] + table[235]) >> 1 == (420 + 9870) >> 1 == 10290/2 == 5145

Because the table values are scaled (and we want unscaled answers) I
am quite sure that my >> 8 is correct. Also, table[255-bg] is not
connected to bg * (255-42)/255, at least not directly. It is alpha
times 255-bg (or 1-bg unscaled).
Some days it just doesn't pay to get out of bed ...

I think a day can be considered just fine if all that goes wrong is a
Usenet post.
 
B

Bartc

Eric Sosman said:
On the assumption that you will push a large number of
pixels through this calculation while keeping `alfa' fixed,
have you considered pre-computing a 256-place lookup table?

The implication seems to be that 'alfa' will be different for each pixel.
 
B

Ben Bacarisse

Bartc said:
The implication seems to be that 'alfa' will be different for each
pixel.

Despite my contributing to the "fixed" alpha discussion it did seem to
be that "32-bit ... with alfa channel" means that the alpha value is
part of each pixel.
 
E

Eric Sosman

Ben said:
Eric Sosman said:
[...]
Some days it just doesn't pay to get out of bed ...

I think a day can be considered just fine if all that goes wrong is a
Usenet post.

If there's one thing I've learned about programming, it's
that the worst thing to do after making a hasty error is to
make a hastier correction. And if there's one thing I keep
forgetting, it's that the worst thing to do after making a
hasty error is to make a hastier correction ...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,951
Messages
2,570,113
Members
46,698
Latest member
alexxx

Latest Threads

Top