Inverting colours of a greyscale image (in java) stored as a byte array

I have an array of bytes, byte bytes[], representing a greyscale image.

I want to invert the colours of this image – so figured I would just flip the bits (bitwise not).

I have attempted this as seen below (have included an extra loop to populate a dummy byte array to allow quick and easy re-creation of my problem)

Random rand = new Random();  
byte bytes[] = new byte[500];

// populate a dummy byte array
for (int i = 0; i < bytes.length; ++i)
    new Random().nextBytes(bytes);

for (int i = 0; i < bytes.length; ++i)
    System.out.print(bytes[i] + "     ");
    //bytes[i] = ~bytes[i]; This throws an error as apparantly java treats a byte array as an integer array?!
    bytes[i] = (byte)~bytes[i]; // This compiles but output not a bitwise not, results displayed below


The results I am getting are:

116 -117

48 -49

70 -71

What I’m looking for is: (I have added the binary manually to fuly illustrate what my understanding of bitwise not (please correct if wrong)

116 (01110100) = (10001011) 139

48 (00110000) = (11001111) 207

70 (01000110) = (10111001) 185

Thanks in advance for any advice

10001011 actually represents -117 (in two’s complement format: ); Java byte type is signed. You probably want unsigned byte values as output (which range from 0 to 255).

As Java byte type is signed, it can only have values from -128 to 127. If you want to have values between 0 and 255 (like 139), you have to use some other type, for example short:

byte b = 116;
short sh = (short) (((short) b) ^ 0xff);

This produces 139.

You can XOR the value with 255, so the particular line should be

bytes[i] = (byte) (bytes[i] ^ 0xff);

You can leave it as it is. It’s already correct, just printed in a confusing way.

For example note that (byte)207 will (by default) be printed as -49. But it’s still the same value, it’s just printed with a different interpretation of the most significant bit.

In short, change nothing.