Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert RGBA to RGB taking background into consideration [duplicate]

Possible Duplicate:
Convert RGBA color to RGB

I'm trying to convert a RGBA color, with a alpha < 1 into a solid RGB representation taking into account the background color.

Using the algorithm provided at this question I manage to get correct conversion to a solid RGB color - BUT ONLY when alpha = 0.5.

Here's my test code:

<!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>

Running the above in both Chrome and Firefox results in successful RGBA->RGB when alpha is 0.5, any deviation away from 0.5 results in a mismatch, very subtle if the deviation is very small (i.e. it's possible to notice the issue when alpha is 0.55).

I've rewritten the logic several times, fully expanding the logic into its most basic parts but I've failed to be successful.

like image 702
seeSaw Avatar asked Jul 23 '12 14:07

seeSaw


People also ask

What is the difference between RGB and RGBA?

An RGB color value represents RED, GREEN, and BLUE light sources. An RGBA color value is an extension of RGB with an Alpha channel (opacity).


1 Answers

It looks like you're trying to use the common method for blending, but the incremental loop is throwing me off. Pulled from the OpenGL FAQ:

"The typical use described above [for blending] modifies the incoming color by its associated alpha value and modifies the destination color by one minus the incoming alpha value. The sum of these two colors is then written back into the framebuffer."

So instead of a while loop, use:

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);
like image 127
AlcoJaguar Avatar answered Sep 30 '22 22:09

AlcoJaguar