Turn hex string into int (JAVA) - java

So I am working on a project where there are 3 sliders(r, g, b) and I use String.format("%02x%02x%02x", r, g, b); to turn it into a hex string, my problem is that I cannot turn it into an int. I have searched the internet and could not find anything, the only one solution was Integer.parseInt(hex, 16) which gives me a value of 87295 and my original color is 0054FF and I get 87295 (the reason I need it as an int is because all of my void methods require a color in a hexadecimal in the form of an int)

Integer.parseInt(String s, 16);
is your friend in need.
Parses the string argument as a signed integer in the radix specified by the second argument... The resulting integer value is returned.
~ Java doc ~
Example:
Integer.parseInt("0054FF", 16);
OUTPUT:
21759
The output does not match your specified output (87295). I believe your error is elsewhere in your code.
EDIT:
According to your comment,
Integer.decode(String s);
is what you need I guess.

My answer assumed you are asking an X - Y problem, which means it may not face to what you need in your question.
Assume r, g, b are of type int, also assume you don't need the Alpha color, then you can use a trick of bit manipulation like this, to directly use the original value to calculate the color value, without turning it into hex string.
int iColor = (r << 16) + (g << 8) + b;
Then this value can be used to turn into hex string for your further need.
String sColorHex = Integer.toHexString(iColor);
Update: Due to the comment of another answer, the alpha should not be ignored, and what the original question really need seems the color int value. Directly use this to get that required value:
int color = 0xFF000000 + (r << 16) + (g << 8) + b;
The original problem doesn't mention about the alpha color, so assume the alpha is 100% (0xFF), which shows as 0xFF000000 (= 0xFF << 24) above.

Related

Multiple bitwise shifts in one statement

I'm trying to write a method that takes in a 32-bit int and an integer number representing a byte in the 32-bit int and return the byte passed in. i.e. getByte(0x56781234, 0); // => 0x34. My thought process is if I can rightshift the int into a position where the byte I want is the last byte of the int, I can AND it with 0xFF to get that value. So something like,
public int getByte(int num, int byteVal) {
return ((num >> 8) >> byteVal) & 0xFF;
}
I know my logic is flawed however. I'm trying to shift multiple times in one statement. Caveat: no multiplication. Advice?
You want to shift right by 0, 8, 16, or 24 depending on the value of byteVal. In your example, you're shifting right by 8 already even if byteVal is 0, so that's not the way.
So, how do you turn 0/1/2/3 into 0/8/16/24.... If only there's a shift operation that might be able to do that!
return (num >> (byteVal << 3)) & 0xFF;

parse String color without java

i have a code like this :
String hex = String.format("0x%02x%02x%02x", r * 0.5, green * 0.6, blue * 0.7));
0.5 and 0.6 and 0.7 are variables
and i want to set background color of a view from variable hex :
v.setBackgroundColor(Integer.parseInt(hex, 16));
When i try to convert it to Hexadecimal integer it throws exceptions like
java.lang.NumberFormatException
how can i do this?
0x causes NumberFormatException. try Integer.decode instead:
v.setBackgroundColor(Integer.decode(hex));
Read:
https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#decode(java.lang.String)
There are potentially three problems with this code:
As #shiftpsh notes: Integer.parseInt does not understand the 0x prefix. There are two ways to solve this:
Use Integer.decode rather that Integer.parseInt.
Don't include the 0x prefix in the format.
The second potential problem is that %02x means hexadecimal, zero-padded with a minimum of two digits. But if any of r, green or blue were large enough, the resulting color value would be greater than 255, and you would get more than 2 hex digits. That would result in an incorrect RGB value when the string is decoded.
I am rather surprised that %02x works for an argument like r * 0.5. The latter is a double and according to my reading of the javadoc the x conversion is not applicable.
However, if the sole point of this code is to create and RGB value from r, green and blue, there is a significantly more efficient way to do it.
int r0 = ((int)(r * 0.5)) & 0xff;
int g0 = ((int)(green * 0.6)) & 0xff;
int b0 = ((int)(blue * 0.7)) & 0xff;
v.setBackgroundColor((r0 << 16) | (g0 << 8) | b0);
Alternatively, using android.graphics.Color.argb to do the RGB conversion should be just as efficient .... though that is an Android API rather than a Java API. (I could not find a directly equivalent Java SE library method that is as efficient.)

How can I mask a hexadecimal int using Java?

I have an integer that contains a hexa value. I want to extract the first characters from this hexa value like it was a String value but I don't want to convert it to a String.
int a = 0x63C5;
int afterMask= a & 0xFFF;
System.out.println(afterMask); // this gives me "3C5" but I want to get the value "63C"
In my case I can't use String utilities like substring.
It's important to understand that an integer is just a number. There's no difference between:
int x = 0x10;
int x = 16;
Both end up with integers with the same value. The first is written in the source code as hex but it's still representing the same value.
Now, when it comes to masking, it's simplest to think of it in terms of binary, given that the operation will be performed bit-wise. So it sounds like you want bits 4-15 of the original value, but then shifted to be bits 0-11 of the result.
That's most simply expressed as a mask and then a shift:
int afterMask = (a & 0xFFF0) >> 4;
Or a shift then a mask:
int afterMask = (a >> 4) & 0xFFF;
Both will give you a value of (decimal) 1596 = (hex) 63C.
In this particular case, as your input didn't have anything in bits 12+, the mask is unnecessary - but it would be if you wanted an input of (say) 0x1263c5 to still give you an output corresponding to 0x63c.
If you want "63C" all you need is to shift right 4 bits (to drop the right most nibble). Like,
int a = 0x63C5;
int afterMask = a >> 4;
System.out.println(Integer.toHexString(afterMask));
Outputs (as requested)
63c
int a = 0x63C5;
int aftermask = a >> 4 ;
System.out.println( String.format("%X", aftermask) );
The mask you need to use is 0XFFF0

Can I simplify reading a short from binary data

I'm trying to simplify some code for decoding data in a file and I've written a test case to show the issue.
Given two bytes as 0xFe and 0xFF I want that to be read as 0xFFFE (65534),
the existing code does
headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256
I thought, if I made buffer byte order little endian, I could get same result by reading as a short. But I do not get same result, why not ?
headerBuffer.getShort();
public void testReadingOfShort() {
ByteBuffer headerBuffer = ByteBuffer.allocate(2);
headerBuffer.order(ByteOrder.LITTLE_ENDIAN);
headerBuffer.put((byte) 0xFE);
headerBuffer.put((byte)0xFF);
headerBuffer.position(0);
int format = headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256;
headerBuffer.position(0);
int formatNew = headerBuffer.getShort();
System.out.println("Format:"+format+"("+ Hex.asHex(format)+")"+":FormatNew:"
+formatNew+"("+Hex.asHex(formatNew)+")");
}
Outputs
Format:65534(0xfffe):FormatNew:-2(0xfffffffffffffffe)
You do get the same value. The problem happens when you assign the short to an int on this line:
int formatNew = headerBuffer.getShort();
When you do this, Java performs sign extension to ensure that the numeric value in the short gets converted to the same numeric value in the int. In your case, that is -2.
The representation of -2 as a short is 0xFFFE, while the int representation is 0xFFFFFFFE. In other words, the sign bit of the short is copied into the additional upper bits of int.
You can address this by not assigning the short to int. You also need to make sure that your Hex.asHex has a proper overload for short, otherwise the same conversion would happen when formatNew gets passed as an argument.
Alternatively, if you would like to treat the value of the short as unsigned, and assign it to an int, you can mask the result with 0xFFFF, like this:
int formatNew = headerBuffer.getShort() & 0xFFFF;
My hypothesis here is that in your Hex class you have a .asHex() method taking a short as an argument which does something like:
int value = (int) argument;
Tough luck. If you "upcast" from one integer type to another, the sign bit, if present, is carried. Which means that if you try and cast short 0xfffe to an int, you will NOT end up with 0x0000fffe but... 0xfffffffe. Hence your result.
If you wanted to cast it as an unsigned value you'd have to mask it, like so:
int value = (int) argument & 0xffff;
You can simply obtain the desired value as
int formatNew = headerBuffer.getShort() & 0xFFFF;
or, alternatively, if you use Java 8:
int formatNew = Short.toUnsignedInt(headerBuffer.getShort());
This will basically drop all bits from the int that are not part of a short. But it won't relieve your from the responsibility of carefully checking where you expect unsigned values, and how to handle the (naturally) signed values in the respective context.

Murmurhash3 between Java and C++ is not aligning

I have 2 separate applications one in Java and the other is C++. I am using Murmurhash3 for both. However, in C++ I get a different result as compared to Java for the same string
Here is the one from C++: https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp?r=144
I am using the following function:
void MurmurHash3_x86_32 ( const void * key, int len,
uint32_t seed, void * out )
Here is the one for Java: http://search-hadoop.com/c/HBase:hbase-common/src/main/java/org/apache/hadoop/hbase/util/MurmurHash3.java||server+void+%2522hash
There are many versions of the same Java code above.
This is how I am making a call for Java:
String s = new String("b2622f5e1310a0aa14b7f957fe4246fa");
System.out.println(MurmurHash3.murmurhash3_x86_32(s.getBytes(), 0, s.length(), 2147368987));
The output I get from Java:
-1868221715
The output I get from C++
3297211900
When I tested for some other sample strings like
"7c6c5be91430a56187060e06fd64dcb8" and "7e7e5f2613d0a2a8c591f101fe8c7351" they match in Java and C++.
Any pointers are appreciated
There are two problems I can see. First, C++ is using uint32_t, and giving you a value of 3,297,211,900. This number is larger than can fit in a signed 32-bit int, and Java uses only signed integers. However, -1,868,221,715 is not equal to 3,297,211,900, even accounting for the difference between signed and unsigned ints.
(In Java 8 they have added Integer.toUnsignedString(int), which will convert a signed 32-bit int to its unsigned string representation. In earlier versions of Java, you can cast the int to a long and then mask off the high bits: ((long) i) & 0xffffffffL.)
The second problem is that you are using the wrong version of getBytes(). The one that takes no argument converts a Unicode String to a byte[] using the default platform encoding, which may vary depending on how your system is set up. It could be giving you UTF-8, Latin1, Windows-1252, KOI8-R, Shift-JIS, EBCDIC, etc.
Never, ever, ever call the no arguments version of String.getBytes(), under any circumstances. It should be deprecated, decimated, defenestrated, destroyed, and deleted.
Use s.getBytes("UTF-8") (or whatever encoding you're expecting to get) instead.
As the Zen of Python says, "Explicit is better than implicit."
I can't tell if there may be any other problems beyond these two.
I had the same problem with you. But the Java version of my Murmurhash3 is different from yours. After making some changes to the C++ version of Murmurhash3, I made the hash values generated from the two versions the same. I give you my solution, which you can use to check if it also works for you.Maybe the biggest difference between the Java and C++ versions lies in the right shift operation(in Java you can see >> and >>>, while in C++ you can only see >>). The integers in Java are all signed, while in C++ you can use signed or unsigned integers. In Java version, the >> means arithmetic right shift and the >>> means logical right shift. And in C++, the >> means arithmetic right shift. The original C++ version of Murmurhash3 uses unsigned integer, and in order to generate the negative hash value like in Java, first in C++ you should change all the unsigned type uint32_t to signed type int32_t. Then you should locate the >>> in Java and make changes around the corresponding >> in C++. For me, I change from:
inline uint32_t rotl32 ( uint32_t x, int8_t r )
{
return (x << r) | (x >> (32 - r));
}
to:
inline int32_t rotl32 ( int32_t x, int8_t r )
{
return (x << r) | (int32_t)((uint32_t)x >> (32 - r)); //similar to >>> in Java
}
and from:
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
to:
FORCE_INLINE int32_t fmix32 ( int32_t h )
{
h ^= (int32_t)((uint32_t)h >> 16); // similar to >>> in Java
h *= 0x85ebca6b;
h ^= (int32_t)((uint32_t)h >> 13);
h *= 0xc2b2ae35;
h ^= (int32_t)((uint32_t)h >> 16);
return h;
}
In this way, my two versions of Murmurhash3 in Java and C++ generate the same hash value.

Categories