Question

I am implementing layers in a 2D engine of mine and I would like layers to be stackable, and I would also like a feature to 'cut holes' in layers - this means using alpha. However when writing it standalone I can't seem to get anything to use true alpha, it tried to fake it by blending colours together, for instance (my code):

BufferedImage background, foreground;
public GraphicsTest() {
    background = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB);
    foreground = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB);  // Fully capable of alpha.
    Random r = new Random();
    int white = Color.white.getRGB();
            // Draw random white dots
    for (int i=0; i<500; i++) {
        int
        x = r.nextInt(500),
        y = r.nextInt(500);
        background.setRGB(x, y, white);
    }
}

@Override
protected void paintComponent(Graphics g) {
    BufferedImage output = new BufferedImage(500,500,BufferedImage.TYPE_INT_ARGB); // Fully capable of alpha.
    Graphics2D canvas = output.createGraphics();
    Graphics2D overlay = foreground.createGraphics();

    canvas.drawImage(background, 0, 0, null);

    overlay.setColor(Color.white);
    overlay.fillRect(0, 0, 500, 500);
            // Start drawing with alpha
    overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
    overlay.setColor(new Color(0xFF000000)); // Overwrite/draw full alpha, colour doesn't matter when alpha is 100%
    overlay.fillRect(100, 100, 125, 87);

    //canvas.setColor(Color.red);
    //canvas.fillRect(0, 0, 500, 500);
    canvas.drawImage(foreground, 0, 0, null);
    overlay.dispose();
    canvas.dispose();
    g.drawImage(output, 0, 0, null);
            // Also write to a file for manual raw pixel checking
    try {
                    // Does output a 32-bit depth image
        ImageIO.write(output, "PNG", new File("c:/output.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This is the most basic test I could think of, I have two images, one for the background and one for the foreground, I am needing to see the background through the foreground in the 127x87 (random sized) box. Currently it results in a white screen with a black box, the back box should be that part of the background.

I have tried all sorts of methods here, settings the composite and drawing black with full alpha but when combined I never see the background, the setColor(0xFF000000) doesn't seem to be doing anything but drawing black and the composite is the culprit of this 'faking', instead of overwriting FF000000 (black) on a 00FFFFFF (white with no alpha) background yielding FF000000 (what I set it to) it is instead 007F7F7F (grey with no alpha).

The only reason I can see for this is the fact that everything is going through a Graphics2D object, I cannot use output.setRGB as it is slow and I wouldn't know how to draw custom shapes with it.

Was it helpful?

Solution

You need to change 3 things for your code to behave properly.

As @vandale said, you need to use a color with actual alpha with the boolean constructor. Second, the alpha is the opacity (so it should be 0 for transparent color). You get:

 overlay.setColor(new Color(0x0000000, true));

Third, you need to say that your paint operation will actually override whatever was already there (you don't want to draw on top (ATOP) of the existing but rather replace with the transparent color (IN) what was there). You get:

 overlay.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1f));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top