# Invert Alpha on Image

I'm making a lighting system right now, and the last part I have to do is to invert the alpha channel on the final light map. My previous code that used to work was

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


But this code threw this "java.lang.ClassCastException: java.awt.image.DataBufferInt cannot be cast to java.awt.image.DataBufferByte" on the first line. So, I changed it to

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


but this doesn't actually invert the alpha, but seems to invert the color between the hue and black? I know that this works

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


But testing this, it brings my framerate down to 15 fps.

So I guess my question is this: Either how can I fix this, or is there a fast way to invert the alpha values of a bufferedimage?

I inverted color in java before and for each channel in the byte array I would subtract the existing value from 255 a bit like so

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
baos.flush();
byte[] imageBytes = baos.toByteArray();
baos.close();
for(int i = 0; i < bytes.length/3; i++)
{
//red
imageBytes[i*4] = (255-imageBytes[i]);
//green
imageBytes[(i*4)+1] = (255-imageBytes[(i*4)+1]);
//Blue
imageBytes[(i*4)+2] = (255-imageBytes[(i*4)+2]);
}


So for an ARGB I would find which order the Alpha comes in assuming its the first byte in order then your code would read

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
baos.flush();
byte[] imageBytes = baos.toByteArray();
baos.close();
for(int i = 0; i < bytes.length/4; i++)
{
//alpha
imageBytes[i*4] = (255-imageBytes[i*4]);
//red
//imageBytes[(i*4)+1] = (255-imageBytes[(i*4)+1]);
//green
//imageBytes[(i*4)+2] = (255-imageBytes[(i*4)+2]);
//Blue
//imageBytes[(i*4)+3] = (255-imageBytes[(i*4)+3]);
}


you would divide bytes.length by 3 for an RGB image and by 4 for an ARGB in the for loop you can then convert to them back to DataBufferByte with

buf.setData(imageBytes);


assuming DataBufferByte works the way I think it does. not hugely familiar with it. I commented the other channels so yo can see what I mean but they aren't needed.

I found this incredibly fast on slow machines as I was able to load and parse an image 512x512 then save it in under a second. I also read somewhere that iterating backwards through an array in java is faster. http://www.mkyong.com/java/reverse-loop-versus-forward-loop-in-performance-java/ I would also note that an ARGB image needs to be png or bmp not jpg like in my example.

• Wouldn't it be for(int i = 0; i < bytes.length; i += 4) instead? – Kyranstar Jan 24 '14 at 5:08
• both for(int i = 0; i < bytes.length; i += 4) and for(int i = 0; i < bytes.length/4; i++) should work fine. In my version you are just shortening the iteration length which is potentially faster – That Homeless Guy Jan 24 '14 at 5:12
• also geekinterview.com/question_details/42577 apparently i++ is faster than i+=1 thus I would assume i++ is faster than i+=4 – That Homeless Guy Jan 24 '14 at 5:37
• I forgot you need to turn imageBytes[i] = (255-imageBytes[i]); into imageBytes[i*4] = (255-imageBytes[i*4]); using my iterator. forgive me it's been a while – That Homeless Guy Jan 24 '14 at 5:42