Alpha blending issue

Feb 17, 2011 at 9:59 AM

Hi,

When I try to blit two images where the second ("source") image contains the alpha information then with the current implemented blit function something goes wrong (colors are wrong).

The correct way of blending should be like this (of course the sample code is very slow and can be optimized by removing the floating stuff):

Color col1,col2,col3;
double fac = col1.A / 255.0;
col3.B = (byte)(col1.B * fac + col2.B * (1 - fac));
col3.R = (byte)(col1.R * fac + col2.R * (1 - fac));
col3.G = (byte)(col1.G * fac + col2.G * (1 - fac));
Regards,

Coordinator
Feb 17, 2011 at 10:23 AM

I'll check this later. Are you sure the colors are off? The sample works fine.

Do you have a repro I could use to test it?

 

- Rene Schulte

Feb 17, 2011 at 11:43 AM

Take 2 arbitrary pictures (with a wide range of colors, e.g. two real-life photos):

// Pic1 and 2 have equal size
WriteableBitmap bmp1 = LoadJpegImage("pic1.jpg");
WriteableBitmap bmp2 = LoadJpegImage("pic2.jpg");

 for (int y = 0; y < bmp1.PixelHeight; y++)
            {
                for (int i = 0; i < bmp1.PixelWidth; i++)
                {
                    int targetIndex = y * bmp1.PixelWidth + i;

                    var c = bmp1.Pixels[targetIndex];
                    var a = 100; // make the picture transparent

                    // Prevent division by zero
                    int ai = a;
                    if (ai == 0)
                    {
                        ai = 1;
                    }

                    // Scale inverse alpha to use cheap integer mul bit shift
                    ai = ((255 << 8) / ai);
                    Color col1 = Color.FromArgb(a,
                                         (byte)((((c >> 16) & 0xFF) * ai) >> 8),
                                         (byte)((((c >> 8) & 0xFF) * ai) >> 8),
                                         (byte)((((c & 0xFF) * ai) >> 8)));

                    bmp1.Pixels[targetIndex] = (col1.A << 24) | (col1.R << 16) | (col1.G << 8) | col1.B;
                }
            }

bmp2.Blit(new Rect(0, 0, (int)ActualWidth, (int)ActualHeight), bmp1, new Rect(0, 0, (int)ActualWidth, (int)ActualHeight), WriteableBitmapExtensions.BlendMode.Alpha);

Coordinator
Feb 17, 2011 at 11:54 AM
Edited Feb 17, 2011 at 11:55 AM

Have you tried to use a PNG image that already has an alpha value applied? The part where the jpeg is made semi-transparent seems not right. As I wrote, Alpha Blending works in the samples.

- Rene Schulte 

Feb 17, 2011 at 12:48 PM

When I replace your Blit function with my blending code (from the first) post, then everything works ok. I think the problem is related to the image stored in the variable "bmp1" because it does not have an alpha value (actually it is automatically set to -1 by the built-in loadjpeg function).

Maybe both alpha values from "bmp1" and "bmp2" are used by Blit?

Coordinator
Feb 17, 2011 at 1:24 PM

Yes, the source and destination alpha values are used. This is the right way to implement a blit. Values of bitmap a and b are mixed.

Just set the alpha value back to 255, use a different jpeg load mechanism or stay with your custom blend mode. 

- Rene Schulte

Feb 17, 2011 at 1:50 PM

Ok, thanks for investigating the "problem".

I am using my own functions, but I just wanted to provide some feedback for the case that there is an implementation error in the Blit function.

Regards,

Coordinator
Feb 17, 2011 at 2:51 PM

OK, you're welcome. As I wrote the blit implementation is correct when it combines both images and doesn't ignore one.

BTW, it's usually better to ask if you're code has some errors or specialties than to claim "The correct way of blending should be like this". ;)

- Rene