0

I'm working with BufferedImage (in PNG) and want to replace a colour with another. I have all colours stored as strings for easy handling but...

for(int x=0;x<output.getWidth();x++)
    for(int y=0;y<output.getHeight();y++)
        if(output.getRGB(x,y)==Integer.parseInt("ffff00fe",16))
            output.setRGB(x,y,Integer.parseInt("ffaaaaaa",16));

the resultant integers should be negative numbers, but it throws NumberFormatException

when I do output.getRGB(x,y) it returns negative numbers on non-transparent pixels

Germán
  • 23
  • 4
  • possible duplicate of [Convert hex string to int](http://stackoverflow.com/questions/11194513/convert-hex-string-to-int) – karvoynistas Feb 04 '15 at 23:01
  • 2
    Are these strings coming from an external source? Because if they're not, just use the hex literals `0xffff00fe` and `0xffaaaaaa` – Ian McLaird Feb 04 '15 at 23:05
  • Even if not, unless the strings are changing each time around the loop it would be better to hoist the conversion out of the loop. (The JIT *may* be smart enough to do that, but I wouldn't count on that.) If you want to see the positive (unsigned) value for those pixels, you can also use `Integer.toUnsignedString(output.getRGB(x, y))` or `Integer.toUnsignedString(output.getRGB(x, y), 16)`. – David Conrad Feb 04 '15 at 23:14
  • `0xffff00fe` _is_ a negative number when interpreted as a 32-bit int. What is the problem? – Jim Garrison Feb 05 '15 at 03:17

3 Answers3

4

You could do

int number = (int)Long.parseLong("ffff00fe", 16);
Reimeus
  • 158,255
  • 15
  • 216
  • 276
0

The number 2,147,483,647 (or hexadecimal 7FFFFFFF) is the maximum positive value for a 32-bit signed binary integer. What you're trying to convert is something almost double that, which means the first bit of the binary number is a 1; in a signed binary integer the first bit being a 1 means it's a negative number.

Basically, you need something bigger to parse it. Try (int) Long.parseLong("ffff00fe", 16) instead of Integer.parseInt("ffff00fe",16)

Aify
  • 3,543
  • 3
  • 24
  • 43
0

Values greater that 0x7fff_ffff are too large to be handled as signed ints. Java 8 has added methods for dealing with ints as if they contained unsigned values. Simply replace parseInt with parseUnsignedInt:

Integer.parseUnsignedInt("ffaaaaaa", 16)

If you need to work with Java 7 and earlier, you can parse it as a long and then cast it to int. Or, if the values are constants, you can write them as numeric constants such as 0xffaaaaaa or even 0xffaa_aaaa and avoid dealing with string conversions (the underscores in numbers are allowed since Java 7 and can make them much easier to read).

David Conrad
  • 15,432
  • 2
  • 42
  • 54