int 颜色的 Alpha 混合超出字节范围

Alpha blending on int colors exceeds byte ranges

提问人:Spook 提问时间:10/28/2023 更新时间:10/28/2023 访问量:13

问:

我已经实现了一种用于 alpha 混合的算法。它工作了一段时间,但很快我就注意到在某些特定情况下我收到了一些奇怪的结果。

我进行了调查,结果发现该算法产生的颜色值大于 255。我编写了一个应用程序来检查颜色/alpha 源/目标值的哪些组合导致了问题:

    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();
        }
    }

结果是直立的可怕的,例如(bA = 碱基 alpha,bR = 碱基红色,tA = 目标 alpha,tR = 目标红):

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

有趣的是,当用浮点算术代替 int 时,结果永远不会超过 256(它们确实超过 255,但我猜是因为浮点算术问题)。

我试图以这样的方式转换公式,即除法(这似乎是四舍五入错误的第一个疑点)总是在计算的末尾,但这并没有太大帮助 - 我总是最终得到超过 255 的结果。

为什么?有没有办法修复公式,这样我就不会收到超过 255 的值?

C# 数学 图形 舍入误差

评论

0赞 Mike 'Pomax' Kamermans 10/28/2023
要正确插值整数,请使用浮点数。然后将最终值转换回 int。
0赞 Spook 10/28/2023
是的。我一开始使用浮点数。我改用 int 计算,因为浮点数太慢了......
0赞 Mike 'Pomax' Kamermans 10/28/2023
这听起来......不可能。但为了说明为什么需要浮点数,请记住整数除法不是正则除法。例如,对于您的示例值,值将是 and,虽然这通常是“几乎 2”,但您使用的是 int 除法。现在是 1,而不是 1.996。如果你解释一下你为什么写你写的代码,可能会有所帮助:每个代码应该做什么?(((bA + tA) * 255) - tA * bA) / 255(((1 + 1) * 255) - 1 * 1) / 255 = ((2*255) - 1) / 255 = 509/255

答: 暂无答案