Java - Decimal color to RGB color - java

I have a decimal (not hexadecimal) color code and, using Java, I need to convert it to the three RGB colors.
So for example, 16777215 (pure white) needs to get converted to Red: 255 Green: 255 Blue: 255.
65280 (pure green) needs to get converted to Red: 0 Green 255: Blue: 0 Here is a converter for more examples.
Just doing some small calculations and playing with the calculator on the page linked above, I have determined:
Red equals 65536 (256^2)
(255x65536 = 16711680, aka pure red)
Green equals 256 (256^1)
(255x256 = 65280, aka pure green)
Blue equals 1 (256^0)
(255x1 = 255, aka pure blue)
I can tell it obviously has something to do with bytes, but I am missing that last little bit. I am not the best with the whole concept of bits/bytes/etc and how it interacts with Java, so it is likely fairly simple.
So, anyone know the best way of going about this? What would be the best way to convert a single numerical decimal color into the three separate RGB values using java?

You where telling right: RGB values are encoded as bytes in a int. R is byte 2, G is byte 1 and B is byte 0, summing up to a 24bit color depth. Depending on the endianess, this could be a possible representation.
00000000 00000000 00000000 00000000 <-- 32bit int
^ ^ ^
| | |
+--red here | +--green here
8bit | 8bit
|
+--blue here
8bit
You can extract RGB values with some bit shift and masking:
int red = (color >> 16) & 0xff;
int green = (color >> 8) & 0xff;
int blue = color & 0xff;

You could do
Color color = new Color(16777215);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();

You can get the channels out by simple bitwise operations.
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = color & 0xff;
From there, it should be easy to do whatever you want with the color information.

Decimal, hexadecimal: does not matter. Your computer uses binary representations internally.
You may have noticed that 0xFF00 == 65280.
Decimal and Hexadecimal are user representations.

I know I am a bit late, but...
int r = color / 65536;
int g = (color - r * 65536) / 256;
int b = color - r * 65536 - g * 256;
This is really doing the exact same thing as the binary shifts even though it doesn't use bitwise operators. This also only works when using valid RGB values (meaning each value is an integer between 0 and 255). For efficiency, however, I would use the binary shifts from the above answers.

Related

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 to hide a char within a pixel

I want to know how to alter the least significant bit(s) of a pixel to hide a character. The picture must remain visually unchanged but I would like to hide a message within it.
To make your problem more specific, let's say you are using a limited 7 bit character set and a plain RGB image (no alpha channel). You can split the character bits into groups of 2-2-3. Since blue is the channel that we see the least variation in, you can hide the 3 bit group in the blue channel. The following encoding/decoding examples will use a Color object to represent the RGB triplet, but the code should work for any equivalent representation:
Encode
Given a pixel that has some original value in the image and a character that you want to encode, replace it with
Color px; // The initial color in the image
char ch; // The character to encode
...
// Store 2,2,3 bits of char in lowest bits of each pixel
// ... & ~0x3 clears the lowest two bits, the or assigns the replacement bits
Color newPx = new Color((px.getRed() & ~0x3) | ((ch & 0x60) >> 5),
(px.getGreen() & ~0x3) | ((ch & 0x18) >> 3),
(px.getBlue() & ~0x7) | (ch & 0x7));
Decode
Color px; // The image pixel with an encoded char
...
char ch = ((px.getRed() & 0x3) << 5) |
((px.getGreen() & 0x3) << 3) |
(px.getBlue() & 0x7);
You have to know what part of the image contains the modified pixels for this to work. Also, make sure that your image data is compressed losslessly if you compress it at all.
To do this, you're going to need to define some convention for mapping your bits. We know that in an ARGB color definition for a pixel, 8 bits are assigned to each the Alpha, Red, Green, and Blue values. As you do not want to map your character entirely over one color, I suspect you will want to break it up evenly over each of the 4 values. You may also not want to edit the alpha, but you can adjust the code I provide fairly easily to accommodate that. Here is how an int is structured. Keep in mind each of the values of the components are 8 bits (range 0-255)
int color = (alpha << 24) | (red << 16) | (green << 8) | blue
which is to say
int blue = color & 0xFF;
int green = (color >> 8) & 0xFF;
int red = (color >> 16) & 0xFF;
int alpha = (color >> 24) & 0xFF;
to hide the rightmost two bits of character c into a component (alpha, red, green, or blue) use
component = (component & 0xFC) | (c & 0x3);
repeat for each color and after each time shift c over two;
c >>= 2;
repackage as a color
int color = (alpha << 24) | (red << 16) | (green << 8) | blue;
to decode, break back into components
int blue = color & 0xFF;
int green = (color >> 8) & 0xFF;
int red = (color >> 16) & 0xFF;
int alpha = (color >> 24) & 0xFF;
then construct your character
char c = ((alpha & 0x3) << 6) | ((red & 0x3) << 4) | ((green & 0x3) << 2) | (blue & 0x3);
this last bit assumes that when you were hiding the bits in the components you went in the order I listed ( alpha, red, green, blue). I hope this helps you with your work, presumable steganography.
Happy coding! Leave a comment if you have any questions.

What does (float)(par4 >> 16 & 255) / 255.0F; mean?

I found this line of code: this.red = (float)(par4 >> 16 & 255) / 255.0F; where red has been declared as a float.
I am trying to understand what it does, especially because the full code is:
this.red = (float)(par4 >> 16 & 255) / 255.0F;
this.blue = (float)(par4 >> 8 & 255) / 255.0F;
this.green = (float)(par4 & 255) / 255.0F;
this.alpha = (float)(par4 >> 24 & 255) / 255.0F;
GL11.glColor4f(this.red, this.blue, this.green, this.alpha);
so I'm guessing this somehow uses different locations of an int (par4) to color text. par4 is equal to 553648127 in this case.
What do those four lines mean, notably the >> 16 & 25?
RGB with alpha channel (usually known as RGBA or aRGB) are four bytes packed into one integer.
AAAAAAAARRRRRRRRBBBBBBBBGGGGGGGG // the original par4, each char represents one bit.
// where ARBG stands for alpha, red, blue and green bit.
The shift and and operator are used to retrieve each individual byte. For example, par4 >> 16 & 255 is first right-shifting the integer 16 bits such that the original 3rd byte is located at base, and the 255 is served as mask to extract only one byte.
And par4 >> 16 will right-shift the original byte 16 bits;
0000000000000000AAAAAAAARRRRRRRR
Finally, applying &255, which is 00000000000000000000000011111111 in bit-representation, will mask the last 8 bits:
0000000000000000AAAAAAAARRRRRRRR
& 00000000000000000000000011111111
= 000000000000000000000000RRRRRRRR
This gives you the red byte.
>> is the right-bit-shift operator. This is more easily seen in binary:
b1000 >> 3 = b0001
You see how it moved the bits right.
& is the bitwise AND operator. The result of x & y will be a value with only the bits in x and y that were both on being on.
b1 & b1 = b1
b1 & b0 = b0
b0 & b1 = b0
b11 & b01 = b01
So
this.red = (float)(par4 >> 16 & 255) / 255.0F;
...takes the value from par4 and shifts the bits right 16 bits to move the "red" value to the rightmost part. Then it masks off anything other than the rightmost byte of that. Then it divides the value (which must be in the range 0 to 255, inclusive) by 255 as a float, resulting in a floating point value between 0.0 and 1 telling us how "red" the color was.
And similarly for blue and green.
Then it uses the same mechanism to determine how strong the alpha channel (transparency) is.
Bitwise-anding with 255 (0b11111111) discards all bits from an integer except the eight least significant bits. If you right-shift first, you can access eight-bit groups from other areas of that integer.
par4 seems to define a color with RGB value and alpha as an integer with 4 bytes.
So the 4 bytes are singled out by shifting the bytes "lower" bytes to the right with the >> operator and masking out the "higher" bytes with the & 255.
Afterwards the byte value is normalized to a float value between 0.0 and 1.0 via the / 255.0f.
If the 4 bytes in our integer are like AARRGGBB, where AA, RR, GG, BB each denote a byte and you e.g. want to single out the red color, you first shift away the green and blue bytes with >> 16, which will leave you with an integer 0000AARR, then you mask out the alpha with the & 255, which will leave you with an integer 00000000RR, where RR is now 1 byte (2 half-bytes) with values between 0 and 255, which you finally transform to a float between 0.0 and 1.0 by division with the / 255.0f.

Combine/compare colors in java

I would like to do 2 things:
Compare two colors (RGB), so that comparer gives me say 1 if the colors are the same and 0 if the compared colors are on the opposite sides of RGB like black and white, and some number from 0 to 1 if they are somehow equal (like both are reddish)
Mix 2 or more colors together to produce a new one: mixing blue and yellow should give me green, mixing red and green should give black etc.
Questions:
Is there any parts of java API which can do something like this for me? If not is there any 3rd part open source java libraries which can facilitate that?
Thanks.
1.
There are many different methods for comparing colors. If you want perceptual dissimilarity, check out the comments of other users. If you just want something simple that gives an indication: use this code:
int rgb1 = ...
int rgb2 = ...
int r, g, b;
r = (rgb1 >> 16) & 0x000000ff;
g = (rgb1 >> 8) & 0x000000ff;
b = rgb1 & 0x000000ff;
r -= (rgb2 >> 16) & 0x000000ff;
g -= (rgb2 >> 8) & 0x000000ff;
b -= rgb2 & 0x000000ff;
double answer = (r*r+g*g+b*b)/(255*255*3.0);
It calculates a euclidean distance and scales it to range from 0 to 1.
2.
Just as there are many different ways to compare colors, there are many ways to combine colors. It depends on what you want.
You could take the average but that's not what you want. As it would darken the resulting color.
EDIT: here is the code to take the average:
r = (rgb1 >> 16) & 0x000000ff;
g = (rgb1 >> 8) & 0x000000ff;
b = rgb1 & 0x000000ff;
r += (rgb2 >> 16) & 0x000000ff;
g += (rgb2 >> 8) & 0x000000ff;
b += rgb2 & 0x000000ff;
int average = ((r/2)<<16)+((g/2)<<8)+(b/2);
If you are somewhat mathematically inclined think about what behavior you actually look for, and try to put it in a formula (or rather 3 formulas, one for red, one for green, and one for blue)
It shouldn't be hard to convert the formula to java code.
You can put individual r, g and b values back into a single rgb value using
int rgb = (r<<16) | (g<<8) | b
Edit: notice that computers work with `red GREEN blue´, where yellow is a combination of green and blue, not the other way around. Conversion can be done, but I have not done it yet. Perhaps conversion between rgb and ryb color spaces may be of help.

Converting pixel color (bytes to bits & bits to bytes)

I wanted to manipulate the image by playing with the pixel bits. So, I wanted to covert the pixels I grabbed from PixelGrabber. The argb value were in bytes. Now I want to convert array of bytes into bits and manipulate it. And then convert back to bytes array.
For Example:
-1057365 into 11101111 11011101 10101011 11111111 and
11101111 11011101 10101011 11111111 into -1057365
Anyone know there's any efficient way to converting between them? Or java has method implemented for it and I don't know.
Thx for helping.
I Assume that the value that you have is a raw 4-byte int representation of the ARGB code.
Each of the channels is 1 byte wide ranging from 0 to 254, together they make up the whole range of 0-255^4 (minus 1).
The best way you can acquire the different channel values is by combination of masking and shifting the argb value into different fields.
int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel ) & 0xff;
Source
You might want to take a look at BitSet.
byte[] argb = ...
BitSet bits = BitSet.valueOf(argb);
bits.set(0); // sets the 0th bit to true
bits.clear(0); // sets the 0th bit to false
byte[] newArgb = bits.toByteArray();
/edit
To convert a byte[] to an int:
int i = 0;
for(byte b : newArgb) { // you could also omit this loop
i <<= 8; // and do this all on one line
i |= (b & 0xFF); // but it can get kind of messy.
}
or
ByteBuffer bb = ByteBuffer.allocate(4);
bb.put(newArgb);
int i = bb.getInt();

Categories