6

重複の可能性:
RGBA カラーを RGB に変換

背景色を考慮して、アルファ < 1 の RGBA カラーをソリッド RGB 表現に変換しようとしています。

この質問で提供されているアルゴリズムを使用して、ソリッド RGB カラーに正しく変換することができましたが、アルファ = 0.5 の場合のみです。

ここに私のテストコードがあります:

<!DOCTYPE html>
<html>
<head></head>
<body>
    <script type="text/javascript">
    // Basic RGB(A) to CSS property value
    function _toString(obj) {
        var type = 'rgb', out = obj.red + ', ' + obj.green + ', ' + obj.blue;

        if (obj.alpha !== undefined) {
            type += 'a';
            out += ', ' + obj.alpha;
        }

        return type + '(' + out + ')';
    }

    // Background color, assume this is always RGB
    var bg = {red: 255, green: 51, blue: 0};
    // RGBA color
    var RGBA = {red: 0, green: 102, blue: 204, alpha: 0};
    // Output RGB
    var RGB = {red: null, green: null, blue: null};
    // Just a cache...
    var alpha;

    while (RGBA.alpha < 1) {
        alpha = 1 - RGBA.alpha;
        RGB.red = Math.round((alpha * (RGBA.red / 255) + ((1 - RGBA.alpha) * (bg.red / 255))) * 255);
        RGB.green = Math.round((alpha * (RGBA.green / 255) + ((1 - RGBA.alpha) * (bg.green / 255))) * 255);
        RGB.blue = Math.round((alpha * (RGBA.blue / 255) + ((1 - RGBA.alpha) * (bg.blue / 255))) * 255);

        document.write('<div style="display: block; width: 150px; height: 100px; background-color: ' + _toString(bg) + '">\
            <div style="color: #fff; width: 50px; height: 50px; background-color: ' + _toString(RGBA) + '"><small>RGBA<br>' + RGBA.alpha + '</small></div>\
            <div style="color: #fff; width: 50px; height: 50px; background-color: ' + _toString(RGB) + '"><small>RGB<br>' + RGBA.alpha + '</small></div>\
        </div>');

        // Increment alpha
        RGBA.alpha += 0.25;
    }
    </script>
</body>
</html>

Chrome と Firefox の両方で上記を実行すると、alpha が 0.5 の場合に RGBA->RGB が成功し、0.5 からの偏差は不一致になり、偏差が非常に小さい場合は非常に微妙です (つまり、alpha が 0.55 の場合に問題に気付く可能性があります)。 )。

ロジックを何度か書き直して、ロジックを最も基本的な部分に完全に拡張しましたが、うまくいきませんでした。

4

1 に答える 1

10

ブレンドに一般的な方法を使用しようとしているように見えますが、インクリメンタル ループが原因です。OpenGL FAQ から引用:

「上記の [ブレンドのための] 典型的な使用法では、関連するアルファ値によって着信カラーを変更し、宛先カラーを 1 から着信アルファ値を引いた値で変更します。これら 2 つのカラーの合計は、フレームバッファに書き戻されます。」

そのため、while ループの代わりに、次を使用します。

alpha = 1 - RGBA.alpha;
RGB.red = Math.round((RGBA.alpha * (RGBA.red / 255) + (alpha * (bg.red / 255))) * 255);
RGB.green = Math.round((RGBA.alpha * (RGBA.green / 255) + (alpha * (bg.green / 255))) * 255);
RGB.blue = Math.round((RGBA.alpha * (RGBA.blue / 255) + (alpha * (bg.blue / 255))) * 255);
于 2012-07-23T14:59:20.337 に答える