Alpha blending on int colors exceeds byte ranges

25 Views Asked by At

I have implemented an algorithm for alpha blending. It worked for some time, but soon I have noticed that I'm receiving some weird results in some specific cases.

I have investigated and it turned out that the algorithm yields color values larger than 255. I wrote an application to check, which combinations of color/alpha source/destination values causes the problem:

    class Program
    {
        static void Main(string[] args)
        {
            var parallelOptions = new ParallelOptions();
            parallelOptions.MaxDegreeOfParallelism = 16;

            Parallel.For(0, 256, parallelOptions, bA =>
            {
                Console.WriteLine($"bA: {bA}...");

                for (int tA = 0; tA < 256; tA++)
                {
                    for (int bR = 0; bR < 256; bR++)
                        for (int tR = 0; tR < 256; tR++)
                        {
                            int a = (((bA + tA) * 255) - tA * bA) / 255;
                            if (a > 0)
                            {
                                var R = ((255u - tA) * bA * bR / 255 + tA * tR) / a;
                                if (R > 255)
                                {
                                    Console.WriteLine($"{bA}, {bR}, {tA}, {tR} => {R}");
                                }
                            }
                         }
                }
            });

            Console.ReadKey();
        }
    }

The results are upright scary, for instance (bA = base alpha, bR = base red, tA = target alpha, tR = target red):

bA, bR, tA,  tR => R
 1, 58,  1, 255 => 312

What is interesting is that when one replaces int with float arithmetic then results never exceed 256 (they do exceed 255, but I guess because floating point arithmetic problems).

I tried to convert the formulas in such way that the division (which seems to be the first suspect for rounding errors) is always in the end of the calculations, but that didn't help too much - I always ended up getting results exceeding 255.

Why is that? Is there a way I can fix the formulas so that I won't receive values exceeding 255?

0

There are 0 best solutions below