2
\$\begingroup\$

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?

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Wouldn't it be for(int i = 0; i < bytes.length; i += 4) instead? \$\endgroup\$ – Kyranstar Jan 24 '14 at 5:08
  • \$\begingroup\$ 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 \$\endgroup\$ – That Homeless Guy Jan 24 '14 at 5:12
  • \$\begingroup\$ also geekinterview.com/question_details/42577 apparently i++ is faster than i+=1 thus I would assume i++ is faster than i+=4 \$\endgroup\$ – That Homeless Guy Jan 24 '14 at 5:37
  • \$\begingroup\$ 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 \$\endgroup\$ – That Homeless Guy Jan 24 '14 at 5:42

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.