Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overlay two images (as byte arrays)

People, i'm sure that it's quite easy, but google didn't helped...

Here is the task - i have two byte arrays (as ARGB), representing my images. They have the same size. What operation i should perform (byte by byte) to overlay one image to another? Second image has some transparency, which must be considered.

To clear, im looking for a code like this:

          bytes[] result = new bytes[first.Length];
          for(i = 0; i< first.Lenght;i++)
          {
               result[i] = first[i] !!%SOMETHING%!! second[i];
          }

Simple guesses like bitwise OR (I know - that's stupid ;) ) don't working.

Thx for your answers.

edit: i can't use standart library becouse of security issues (all this strange manipulations occur on Silverlight).

like image 583
ALOR Avatar asked Dec 02 '25 21:12

ALOR


1 Answers

Assuming that you are in fact working with bitmaps, you'll likely find it easier to just let the library do this for you.

The System.Drawing.Graphics class has a CompositingMode property that can be set to either SourceCopy (the default - overwrites the background colour) or SourceOver (blends with the background color).

See MSDN: How to Use Compositing Mode to Control Alpha Blending for more detail.

If you just want the raw math, alpha blending is pretty simple. For an alpha value a between 0.0 and 1.0, the result should be:

(aOld * oldValue) + ((1 - aOld) * aNew * newValue)

Where oldValue is the previous value before overlay, newValue is what you want to overlay with, and aOld and aNew are the old and new alpha values respectively. You obviously need to do this calculation for the R, G, and B values separately.

See also: Alpha Compositing (wiki link) for a more thorough explanation.


Update: I think it should be easy to figure out how to adapt this to the code in the OP, but I guess not everybody's a math person.

I'm going to assume that the byte[] is a repeating sequence of A, R, G, B values (so Length would be a multiple of 4). If that's not the case, then you'll have to adapt this code to whatever storage format you're using.

bytes[] result = new bytes[first.Length];
for(i = 0; i < first.Length; i += 4)
{
    byte a1 = first[i];
    byte a2 = second[i];
    byte r1 = first[i+1];
    byte r2 = second[i+1];
    byte g1 = first[i+2];
    byte g2 = second[i+2];
    byte b1 = first[i+3];
    byte b2 = second[i+3];

    byte a = a1 + (255 - a1) * a2 / 255;
    byte r = r1 * a1 / 255 + r2 * (255 - a1) * a2 / 65025;
    byte g = g1 * a1 / 255 + g2 * (255 - a1) * a2 / 65025;
    byte b = b1 * a1 / 255 + b2 * (255 - a1) * a2 / 65025;

    result[i] = a;
    result[i+1] = r;
    result[i+2] = g;
    result[i+3] = b;
}
like image 113
Aaronaught Avatar answered Dec 04 '25 09:12

Aaronaught



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!