lynks
lynks

Reputation: 5689

Java Invert Image Alpha

I have a situation where I need to invert the alpha channel of a VolatileImage

My current implementation is the obvious, but very slow;

public BufferedImage invertImage(VolatileImage v) {
    BufferedImage b = new BufferedImage(v.getWidth(), v.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
    Graphics g = b.getGraphics();
    g.drawImage(v, 0, 0, null);
    for(int i = 0; i < b.getWidth(); i++) {
        for(int(j = 0; j < b.getHeight(); j++) {
            Color c = new Color(b.getRGB(i, j, true));
            c = new Color(c.getRed(), c.getGreen(), c.getBlue(), 255 - c.getAlpha());
            b.setRGB(i, j, c.getRGB());
        }
    }
    return b;
}

This works fine, but is painfully slow. I have large images and need this to be fast. I have messed around with the AlphaComposite but to no avail - this is not really a composting problem as far as I understand.

Given that 255 - x is equivalent to x & 0xff for 0 <= x < 256, can I not do an en-masse XOR over the alpha channel somehow?

Upvotes: 0

Views: 2502

Answers (2)

lynks
lynks

Reputation: 5689

After a lot of googleing, I came across DataBuffer classes being used as maps into BufferedImages:

DataBufferByte buf = (DataBufferByte)b.getRaster().getDataBuffer();
byte[] values = buf.getData();
for(int i = 0; i < values.length; i += 4) values[i] = (byte)(values[i] ^ 0xff);

This inverts the values of the BufferedImage (you do not need to draw it back over, altering the array values alters the buffered image itself).

My tests show this method is about 20 times faster than jazzbassrob's improvement, which was about 1.5 times faster than my original method.

Upvotes: 2

devrobf
devrobf

Reputation: 7213

You should be able to speed it up by avoiding all the getters and the constructor inside the loop:

for(int i = 0; i < b.getWidth(); i++) {
    for(int(j = 0; j < b.getHeight(); j++) {
        b.setRGB(b.getRGB(i, j) ^ 0xFF000000);
    }
}

Upvotes: 1

Related Questions