0
\$\begingroup\$

I'm using java and I do pixel-by-pixel rendering (a pixel array from an ARGB BufferedImage). So a color is 0xAARRGGBB. Now how can I render a transparent color? I guess that I should manipulate the existing pixel and not overwrite it. I can make color addition simply:

public static int additiveColor(int c1, int c2) {
        int red = (c1 & 0x00ff0000) + (c2 & 0x00ff0000);
        int grn = (c1 & 0x0000ff00) + (c2 & 0x0000ff00);
        int blu = (c1 & 0x000000ff) + (c2 & 0x000000ff);
        return 0xff000000 + (red > 0x00ff0000 ? 0x00ff0000 : red) + (grn > 0x0000ff00 ? 0x0000ff00 : grn) + (blu > 0x000000ff ? 0x000000ff : blu);
    }

So to set a pixel to a sum of two colors I just do this:

pixels[i] = additiveColor(c1, c2);

How can I do transparency?

\$\endgroup\$
1
\$\begingroup\$

You want linear interpolation using the alpha channel of the incoming (source) pixel.

This goes by different names in different APIs (mix (...) in OpenGL, lerp (...) in D3D). No matter what you call it, it boils down to the following:

public static int alpha_blend(int c1, int c2) {
    int a1 = (c1 & 0xff000000) >>> 24;
    //int a2 = (c2 & 0xff000000) >>> 24; // Do not need for traditional alpha blending

    int r1 = (c1 & 0x00ff0000) >> 16;
    int r2 = (c2 & 0x00ff0000) >> 16;

    int g1 = (c1 & 0x0000ff00) >> 8;
    int g2 = (c2 & 0x0000ff00) >> 8;

    int b1 = (c1 & 0x000000ff);
    int b2 = (c2 & 0x000000ff);

    float src_alpha = ((float)a1) / 255.0f;

    int red   = (r1 * src_alpha) + (r2 * (1.0f - src_alpha));
    int green = (g1 * src_alpha) + (g2 * (1.0f - src_alpha));
    int blue  = (b1 * src_alpha) + (b2 * (1.0f - src_alpha));

    return (a1 << 24) | (red << 16) | (green << 8) | blue;
}

You might need some casts to make Java happy, I would not consider this more than pseudo-code to give you an idea of what needs to happen.

\$\endgroup\$
7
  • \$\begingroup\$ Hmm... there's something weird about the green and blue. If I render a red rectangle, I get a red one. But if I render a blue rectangle, I get a white one, and if I render a green one, I get a yellow one. \$\endgroup\$
    – LPeter1997
    Dec 6 '14 at 18:55
  • \$\begingroup\$ @LPeter1997: Can I ask how the values of c1 and c2 are determined? I am operating under the assumption that c2 is the color of what's already rendered and c1 is the color you are trying to blend. If you could show a screenshot of the situation you are describing, that might help. \$\endgroup\$ Dec 6 '14 at 19:03
  • \$\begingroup\$ Here is a screenshot: fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-xpa1/v/t34.0-12/… And the rendering: pixels[pos] = ColorUtils.alphaBlend(color, pixels[pos]); \$\endgroup\$
    – LPeter1997
    Dec 6 '14 at 19:14
  • \$\begingroup\$ @LPeter1997: I think the fact that Java doesn't have unsigned data types is causing this. If that is the case, then the operator you need to use when calculating a1 is actually >>> rather than >>. \$\endgroup\$ Dec 6 '14 at 19:28
  • \$\begingroup\$ Thanks, now the colors are correct, except for the white parts around the red dots. \$\endgroup\$
    – LPeter1997
    Dec 6 '14 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.