I'm trying to convert a signed int variable to a 3 byte array and backwards.
In the the function getColorint, I'm converting the int value to the byte array. That works fine!
public byte [] getColorByte(int color1){
byte[] color = new byte[3];
color[2] = (byte) (color1 & 0xFF);
color[1] = (byte) ((color1 >> 8) & 0xFF);
color[0] = (byte) ((color1 >> 16) & 0xFF);
return color;
}
But if I try to convert the byte array back to the Integer with the getColorint function:
public int getColorint(byte [] color){
int answer = color [2];
answer += color [1] << 8;
answer += color [0] << 16;
return answer;
}
it only works for positive integer values.
Here is a screenshot during the debug:
My input int value is -16673281 but my output int value is 38143.
Can anyone help me?
Thanks :)
The Color class defines methods for creating and converting color ints. Colors are represented as packed ints, made up of 4 bytes: alpha, red, green, blue.
You should use it.
The problem here is that byte is signed. When you do int answer = color[2] with color[2] == -1, then answer will be also -1, i.e. 0xffffffff, whereas you want it to be 255 (0xff). You can use Guava 's UnsignedBytes as a remedy, or simply take color[i] & 0xff which casts it to int.
As is Color represents in 4 bytes, you should store also an alpha channel.
From Int :
public byte [] getColorByte(int color1){
byte[] color = new byte[4];
for (int i = 0; i < 4; i++) {
color [i] = (byte)(color1 >>> (i * 8));
}
return color;
}
To Int :
public int getColorInt(byte [] color){
int res = ((color[0] & 0xff) << 24) | ((color[1] & 0xff) << 16) |
((color[2] & 0xff) << 8) | (color[3] & 0xff);
return res;
}
Related
I am working with some low capacity module and I need to compress the data as much as possible. The data will look like this:
DeviceEvent:
1 byte:
2 bits for status (00 each time)
6 bits for rgb color (3 x 2 bits)
2 bytes: number of minutes from now to a certain datetime
I need to create a constructor (preferably 2 constructors) for conversion from/to:
Event:
byte[] color (rgb, colors will get simplified to only 64 available)
some datetime (but I will get the integer for difference in minutes and it will be small enough to fit in two bits)
So basically I need:
byte[3] color <-> 1 byte status and color
int minutes <-> byte[2]
minutes
I will be thankful for any help
I'm not very sure what is your problem, probably this will help:
final byte red = 1; // 01 binary
final byte green = 2; // 10 binary
final byte blue = 3; // 11 binary
final byte finalColor = (byte) ((red & 0x3) << 4) | ((green & 0x3) << 2) | (blue & 0x3);
System.out.println(finalColor);// finalColor is 011011 = 27 decimal
final int minutes = 0x1234; // first byte is 0x12, second byte is 0x34
final byte[] bytes = {(byte) (((minutes) >>> 8) & 0xff), (byte) (minutes & 0xff)};
System.out.println(bytes[0]); // 0x12 = 18 decimal
System.out.println(bytes[1]); // 0x34 = 52 decimal
I am not sure what the second problem is. So I made these two functions that might help you:
public static int convertToInt(int a, int b, int c, int d) {
a = Math.min(a, 255);
b = Math.min(b, 255);
c = Math.min(c, 255);
d = Math.min(d, 255);
return ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | (d & 0xFF);
}
public static int[] extractComponents(int data) {
int a = (data >> 24) & 0xFF;
int b = (data >> 16) & 0xFF;
int c = (data >> 8) & 0xFF;
int d = data & 0xFF;
return new int[] {a, b, c, d};
}
The convertToInt function takes four numbers(that are less than 255) and puts them all in one int.
The extractComponents function does the opposite.
This is an example:
int data = 0xC8E0601B;
int[] dataA = extractComponents(data);
for(int i = 0 ; i < dataA.length; i++) System.out.printf("%x\n", dataA[i]);
System.out.printf("%x\n", convertToInt(dataA[0], dataA[1], dataA[2], dataA[3]));
I am trying to convert a byte to integer. All the searches I have done use byte[] which I assume is any array. I want to convert F byte (not b as show below) but it gives error to change: not applicable to the argument.
byte F;
mmInStream.read(packetBytes);
b [counter]= packetBytes[0];
F=b [counter];
counter++;
temp = byteToInt(b); //Convert byte to int
Here is a byte To Int I found on one of the sites.
private int byteToInt(byte[] b) {
int value= 0;
for(int i=0;i<b.length;i++){
int n=(b[i]<0?(int)b[i]+256:(int)b[i])<<(8*i);
value+=n;
}
return value;
}
Simply do:
byte b = ...;
int signedInt = b; // For negative bytes, resulting in negative ints
int unsignedInt = 0xFF & b; // For negative bytes, resulting in positive ints
FYI: An int is 4 bytes. So, that is the reason why the methods you found on the internet are using an array of bytes. They assume you pass an array of 4 bytes, which will be stitched together to make an int.
you can use this:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
or this one also:
public static byte[] intToByteArray(int a)
{
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
and
public static int byteArrayToInt(byte[] b)
{
return (b[3] & 0xFF) + ((b[2] & 0xFF) << 8) + ((b[1] & 0xFF) << 16) + ((b[0] & 0xFF) << 24);
}
if b is unsigned
int i = b & 0xff;
Actually I need to transfer the integer value along with the bitmap via bluetooth.. Now my problem is I need to transfer the integer as single byte value..
Is tat possible to convert int as single byte value.. and retrieve it as a integer there... I tried byteValue() and the casting thing but its not usefull.. If my approach is right just help me out with this or say some other way.
(Each time when I am using casting then it's returning as 65535)
What about this?
public static byte[] intToByteArray(int a)
{
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
and
public static int byteArrayToInt(byte[] b)
{
return (b[3] & 0xFF) + ((b[2] & 0xFF) << 8) + ((b[1] & 0xFF) << 16) + ((b[0] & 0xFF) << 24);
}
If you're completely sure, that your int variable contains a byte value [-128; 127] then it should be as simple as:
int i = 100; // your int variable
byte b = (byte) i;
A single byte (8 bits) can only contain 2^8 unsigned integers, i.e [0, 255]. For signed you loose the first bit and the range becomes [-128, 127]. If your integer fits then a simple cast should work.
for 0-255 numbers.
int i = 200; // your int variable
byte b = (byte)(i & 0xFF);
This is probably easy, but I'm trying to convert from a source which provides colors in RGB strings to an output in BGR strings in Java. I've been busting my brain and time on shifting and Long.decode and Long.toHexString.
Feel free to also throw alpha values in there (RGBA -> ABGR), though I think I can extend the principles.
I can assume that the hex is in the form specified in the long and int decode:
0x HexDigits
0X HexDigits
# HexDigits
For 24bit colors (8 bits to each of R,G,B):
String rgbSource = getRGBSource(); //your function to get a string version of it
int in = Integer.decode(rgbSource);
int red = (in >> 16) & 0xFF;
int green = (in >> 8) & 0xFF;
int blue = (in >> 0) & 0xFF;
int out = (blue << 16) | (green << 8) | (red << 0);
int abgr = Integer.reverseBytes(rgba);
Including supporting code, with the assumption that it is safe to decide whether alpha needs adding based on the string length (consider "0xFFFFFF".length() for example):
String rgb = getRGB();
//decodes a number of hex formats and sets alpha
int rgba = rgb.length() < 8 ?
Long.decode(rgb + "ff").intValue() :
Long.decode(rgb ).intValue();
int abgr = Integer.reverseBytes(rgba);
Here's a one line method:
public static String reverseRGB(String rgba) {
return String.format("%08X",Integer.reverseBytes(Long.decode(rgba.length() < 8 ? rgba + "ff" : rgba).intValue()));
}
If the input is a 6 character rgb string:
String bgr = rgb.substring(4,6) + rgb.substring(2,4) + rgb.substring(0,2);
If the input is an 8 character rgba string:
String abgr = rgba.substring(6,8) + rgba.substring(4,6) + rgba.substring(2,4) + rgba.substring(0,2);
If the input is an int with 8 bit channels:
String bgr = String.format( "%02X%02X%02X" , rgb & 0x00FF , (rgb>>8) & 0x00FF , (rgb>>16) & 0x00FF );
String abgr = String.format( "%02X%02X%02X%02X" , rgba & 0x00FF , (rgba>>8) & 0x00FF , (rgba>>16) & 0x00FF , (rgba>>24) & 0x00FF );
// or
String bgr = String.format( "%06X" , Integer.reverseBytes( rgb ) >> 8 );
String abgr = String.format( "%08X" , Integer.reverseBytes( rgba ) );
Here is how I got it to work, but I really hope there is a better way because this is awful. Please come up with a cleaner, more efficient way to do this, so I can give you rep.
long number = (rgb.length() < 8 ? Long.decode(rgb+ "ff") : Long.decode(rgb)); //decodes a number of hex formats and sets alpha
String abgrColor = (new StringBuilder())
.append((Long.toHexString((number) & 0xFF).length()==2? Long.toHexString((number) & 0xFF): "0"+Long.toHexString((number) & 0xFF)))
.append((Long.toHexString((number>>8) & 0xFF).length()==2? Long.toHexString((number>>8) & 0xFF): "0"+Long.toHexString((number>>8) & 0xFF)))
.append((Long.toHexString((number>>16) & 0xFF).length()==2? Long.toHexString((number>>16) & 0xFF): "0"+Long.toHexString((number>>16) & 0xFF)))
.append((Long.toHexString((number>>24) & 0xFF).length()==2? Long.toHexString((number>>24) & 0xFF): "0"+Long.toHexString((number>>24) & 0xFF)))
.toString();
This should work.
public static int swapByte1And3(int inValue) {
int swap = inValue & 0xFF;
swap = swap << 16 | (inValue >>> 16 & 0xFF);
return inValue & 0xFF00FF00 | swap;
}
public static int convertBRGtoRBG(int inColor) {
return swapByte1And3(inColor);
}
public static int convertABRGtoRBGA(int inColor) {
int swap = inColor >>> 24;
inColor = convertBRGtoRBG(inColor) << 8;
return inColor | swap;
}
Given
private int width = 400;
private byte [] data = new byte [2];
I want to split the integer "width" into two bytes and load data[0] with the high byte and data[1] with the low byte.
That is binary value of 400 = 1 1001 0000
so data[0] should contain 0000 0001
and data[1] should contain 1001 0000
Using simple bitwise operations:
data[0] = (byte) (width & 0xFF);
data[1] = (byte) ((width >> 8) & 0xFF);
How it works:
& 0xFF masks all but the lowest eight bits.
>> 8 discards the lowest 8 bits by moving all bits 8 places to the right.
The cast to byte is necessary because these bitwise operations work on an int and return an int, which is a bigger data type than byte. The case is safe, since all non-zero bits will fit in the byte. For more information, see Conversions and Promotions.
Edit: Taylor L correctly remarks that though >> works in this case, it may yield incorrect results if you generalize this code to four bytes (since in Java an int is 32 bits). In that case, it's better to use >>> instead of >>. For more information, see the Java tutorial on Bitwise and Bit Shift Operators.
For converting two bytes the cleanest solution is
data[0] = (byte) width;
data[1] = (byte) (width >>> 8);
For converting an integer to four bytes the code would be
data[0] = (byte) width;
data[1] = (byte) (width >>> 8);
data[2] = (byte) (width >>> 16);
data[3] = (byte) (width >>> 24);
It doesn't matter whether >> or >>> is used for shifting, any one bits created by sign extension will not end up in the resulting bytes.
See also this answer.
This should do what you want for a 4 byte int. Note, it stores the low byte at offset 0. I'll leave it as an exercise to the reader to order them as needed.
public static byte[] intToBytes(int x) {
byte[] bytes = new byte[4];
for (int i = 0; x != 0; i++, x >>>= 8) {
bytes[i] = (byte) (x & 0xFF);
}
return bytes;
}
Integer is 32 bits (=4 bytes) in java, you know?
width & 0xff will give you the first byte,
width & 0xff00 >> 8 will give you the second, etc.
To get the high byte, shift right by 8 bits then mask off the top bytes. Similarly, to get the low byte just mask off the top bytes.
data[0] = (width >> 8) & 0xff;
data[1] = width & 0xff;
int width = 400;
byte [] data = new byte [2];
data[0] = (byte) ((width & 0xFF00) >> 8);
data[1] = (byte) (width & 0xFF);
for(int b = 0; b < 2; b++) {
System.out.println("printing byte " + b);
for(int i = 7; i >= 0; i--) {
System.out.println(data[b] & 1);
data[b] = (byte) (data[b] >> 1);
}
}
I suggest you have a look at the source for HeapByteBuffer. It has the conversion code for all primitive data types. (In fact you could just use a ByteBuffer ;)