Matt Clark
Matt Clark

Reputation: 28589

Combining two Color integers with transparency in Java

I am working on a project which requires me to manually calculate the color of each pixel color I am working with and combining two together.

The bottom pixel color will always have a 100% opacity, however the top will not, and can contain any level of opacity.

I am trying to create an algorithm to combine the colors so that the opacity will have an actual effect, and the below is what I currently have:

public static int combine(int bottom, int top) {

    int tAlpha = Color.alpha(top);

    if (tAlpha < 255 && tAlpha > 0) {

        int tRed = Color.red(top);
        int tGreen = Color.green(top);
        int tBlue = Color.blue(top);

        int bRed = Color.red(bottom);
        int bGreen = Color.green(bottom);
        int bBlue = Color.blue(bottom);

        int cRed = (int) (bRed + (tRed * (Float.valueOf(tAlpha) / 255)));
        int cGreen = (int) (bGreen + (tGreen * (Float.valueOf(tAlpha) / 255)));
        int cBlue = (int) (bBlue + (tBlue * (Float.valueOf(tAlpha) / 255)));

        cRed = (cRed <= 255) ? cRed : 255;
        cGreen = (cGreen <= 255) ? cGreen : 255;
        cBlue = (cBlue <= 255) ? cBlue : 255;

        return Color.argb(255, cRed, cGreen, cBlue);

    } else if (tAlpha == 0) {

        return bottom;

    } else if (tAlpha == 255) {

        return top;

    } else {

        return 0;

    }

}

The problem that I am having with this algorithm, is some pixels will have an aRGB value of (???, 0, 0, 0), and following this code, the bottom pixel color will prevail, instead of the value being darkened by the alpha.

Any solutions as to how that can be improved would be greatly appreciated.

Upvotes: 4

Views: 2104

Answers (1)

Ted Hopp
Ted Hopp

Reputation: 234795

Using the standard alpha blending formulas, you should be computing the output color using:

cRed = (tRed * tAlpha + bRed * (255 - tAlpha)) / 255;

and similarly for the blue and green channels. This just sets each rgb channel to a linear interpolation of the corresponding top and bottom channel values according to where tAlpha is in the range [0, 255]. I don't believe you need to worry about clamping; each component will remain in the range [0, 255].

Of course you can take shortcuts for the special cases of tAlpha == 0 and tAlpha == 255.

Upvotes: 6

Related Questions