I'm trying make program which convert hex to decimal rgb888 and rgb565 respectively.
I’m already did my program to convert hex to rgb888 format, and my code looks like this:
String color = "0xFFFF00";
int hexToRgb = 0;
color.toLowerCase();
String[] colorSplited = color.split("0x");
String splitedConverted = colorSplited[1];
int R = Integer.valueOf(splitedConverted.substring(0,2), 16);
int G = Integer.valueOf(splitedConverted.substring(2,4), 16);
int B = Integer.valueOf(splitedConverted.substring(4,6), 16);
System.out.println(R + " " + G + " " + B);
I saw some articles where they explained that each rgb888 component R, G and B is variated by 0 and 2^8. My currently program don’t use that specific process but I got the results which I needed.
Now I need make the same program but to convert hex to rgb565,. My hex input looks like this:
String color = “0xFFE0”;
So which will be converted is FFE0.
To this input I need get the result R = 31, G = 63 and B = 0. But I have no idea how I achieve this result.
What I got in the internet was to each component RGB is variated by 0 <= R <= 2^5, 0 <= G <= 2^6 and 0 <=B <= 2^5.
Unfortunately I’m not an expert in math.
Can someone help me understand the math behind this or have any sugestions about how I can get this result?
First of all, each hexadecimal character is codified by 4 bits. Therefore, having 4 hex characters means you have 16 bits to code a color.
RGB565 uses 5 bits for red, 6 bits for green and 5 bits for blue. Having n bits for a color means it'll have 2^n possible values. 2^5 = 32 and 2^6 = 64, this is where the different values for each color you got from the Internet come from.
To split the RGB565 value into each separate color you would need to extract the corresponding bits for each one of them, for example, like this:
int redMask = 0b1111100000000000;
int greenMask = 0b0000011111100000;
int blueMask = 0b0000000000011111;
String color = "0xFFE0";
int colorAsInteger = Integer.parseInt(color.substring(2,color.length()), 16); // convert the Hex value to int
int R = (colorAsInteger & redMask) >> 11; // keep only red bits
int G = (colorAsInteger & greenMask) >> 5; // keep only green bits
int B = colorAsInteger & blueMask; // keep only blue bits
System.out.println(R + " " + G + " " + B);
The typical hex representation of RGB colors is the same as RGB888, i'll try to show this with examples. Guess we've got the color
0xFF8800, which is literally
1111.1111.1000.1000.0000.0000 as a binary number, where its components are:
R = FF = 1111.1111 = 255(dots are only for helping the view)
G = 88 = 1000.1000 = 136
B = 00 = 0000.0000 = 0
So, the translation is immediate (well, there's no translation indeed), and each component can have a value from 00 to FF (0 to 255 in decimal base)
The case with RGB565 is different. You only have 5 bits (or 6 in case of green) to represent that component of the color.
You can see each component as the percentage of participation in the global color.
In the example of 0xFF8800:
Red component participates with a 100% (it has the maximum possible value for a component, 255)
Green participates with a 53.33% (it has the value 136 over 255)
Blue participates with a 0%, this one is obvious.
If you apply this percentages of color to the RGB565 color, you will got the values of each component.
So, to translate 0xFF8800 to RGB565, calculate each percentage
R = 1 * 31 = 31 //(percentage over 100 by the maximum value of red in RGB565 = 2^5, minus 1)
G = 0.5333 * 63 = 33.6 //(you should round this value to integer)
B = 0 * 31 = 0
With this, the final number is:
31 34 0
11111.100010.00000
or
1111.1100.0100.0000
in hex
0xFC40
Not sure if the explanation is the best, but hope it helps.
You cannot simply split the string like you were doing for the rgb888 format.
What you should do is converting the full string to a number and then split this number using bit shifting like this :
String color = "0xFFE0";
int rgb = Integer.valueOf(color.substring(2,6), 16);
int r = (rgb & 0b1111100000000000) >> 11;
int g = (rgb & 0b0000011111100000) >> 5;
int b = (rgb & 0b0000000000011111) >> 0;
Related
I am trying to develop a program to read certain type of file and extract all the package information of this file in bit level.
The packet is divided as:
SYC: 8 bits
TEI: 1 bits
PSI: 1 bit
TP: 1 bit
PID: 13 bits
TSC: 2 bits
AFC: 2 bits
CC: 4 bits
My question is: how do I get the bits separately? For example the PID, 5 bits are in position 1 of the array and 8 bits in position 2; how can I get this information from 2 separate bytes and sum them afterwards?
I have this sample code to get the PID and it reproduces the correct result:
int PID1 = (buf [1] << 8) | (buf [2] & 0xff);
I don't understand this equation, especially buf [1] << 8. Could someone explain to me this equation and what should I do to get the rest of the package information?
The '<<' operator moves the bits position to the right in binary which is essentially the same as multiplying by two.
This code :
byte buf[] = new byte[2];
buf[1] = 3;
for (int i = 0; i < 9; i++) {
int bshifted = buf[1]<<i;
System.out.println("buf[1]<<"+i+" = " + Integer.toBinaryString(bshifted) +"(binary) = "+ bshifted + "(decimal)");
}
Produces this output:
buf[1]<<0 = 11(binary) = 3(decimal)
buf[1]<<1 = 110(binary) = 6(decimal)
buf[1]<<2 = 1100(binary) = 12(decimal)
buf[1]<<3 = 11000(binary) = 24(decimal)
buf[1]<<4 = 110000(binary) = 48(decimal)
buf[1]<<5 = 1100000(binary) = 96(decimal)
buf[1]<<6 = 11000000(binary) = 192(decimal)
buf[1]<<7 = 110000000(binary) = 384(decimal)
buf[1]<<8 = 1100000000(binary) = 768(decimal)
The whole expression (buf [1] << 8) | (buf [2] & 0xff) has the effect of moving buf[1] out of the low order 8 bits of the int and putting only the low order 8 bits of buf[2] into that part of the integer.
The following code is part of a working camera app that detects motion and saves preview, painting the moving parts red.
public class RgbMotionDetection implements IMotionDetection {
that detects motion
private static final int mPixelThreshold = 50; // Difference in pixel (RGB)
private static final int mThreshold = 10000; // Number of different pixels
private static int[] mPrevious = null;
private static int mPreviousWidth = 0;
private static int mPreviousHeight = 0;
/**
* {#inheritDoc}
*/
#Override
public int[] getPrevious() {
return ((mPrevious != null) ? mPrevious.clone() : null);
}
protected static boolean isDifferent(int[] first, int width, int height) {
if (first == null) throw new NullPointerException();
if (mPrevious == null) return false;
if (first.length != mPrevious.length) return true;
if (mPreviousWidth != width || mPreviousHeight != height) return true;
int totDifferentPixels = 0;
for (int i = 0, ij = 0; i < height; i++) {
for (int j = 0; j < width; j++, ij++) {
int pix = (0xff & ((int) first[ij]));
int otherPix = (0xff & ((int) mPrevious[ij]));
// Catch any pixels that are out of range
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
if (otherPix < 0) otherPix = 0;
if (otherPix > 255) otherPix = 255;
if (Math.abs(pix - otherPix) >= mPixelThreshold) {
totDifferentPixels++;
// Paint different pixel red
first[ij] = Color.RED;
}
}
}
I'd like to understand this fully in order to be able to modify.
The line that really puzzles me is:
int pix = (0xff & ((int) first[ij]));
What does it do?
thanks
Dave
Forgive me if I explain something now that you know but I want to make this a self contained answer.
The colors of a pixel can be stored in an integer. An integer in Java consist of four bytes, a color typically (in this context) is represented with four bytes: One byte each for red, green, and blue, the last byte for transparency. The mix of the subpixels on screen results in the observed color.
So the following integer represents a color:
0 0 f f c c a a (Hexadecimal representation)
0000 0000 1111 1111 1100 1100 1010 1010 (Binary representation)
Transp.-- Red------ Green---- Blue----- (Color interpretation)
16764074 (Decimal representation, quite useless here)
In this case the first two bytes (00) represent the transparency, ff the red subpixel, cc the green, aa the blue.
If we want to get only a single part of this, e.g. the blue subpixel, we need a bit mask.
0000 0000 1111 1111 1100 1100 1010 1010 (Binary representation)
& (Binary AND: Return 1 if both bits are 1)
0000 0000 0000 0000 0000 0000 1111 1111 (Bitmask for blue, in hex 0x000000ff)
=
0000 0000 0000 0000 0000 0000 1010 1010
This is the result of the operation in the line you mention, it just uses the shorthand hex interpretation for the mask:
int pix = (0xff & ((int) first[ij]));
As the array first already is an int array the cast of first[ij] is useless.
If you want another part of the pixel, say the green part, you need to shift the mask (or use a hardcoded value) and need to shift back the result:
00ffccaa
&
0000ff00 Hardcoded, alternative: ff << 8
=
0000cc00
Shift the result to the rightmost position within the integer
0000cc00 >> 8 = 000000cc
Similar with 16 and 24 for red resp. transparency.
So the line gives you the value of the blue subpixel of the pixel. This value is in the range of 0..255, as these are the only values possible with eight bits (when interpreted as unsigned byte or stored in a Java int as it is done here; Java bytes are signed and wouldn't use that decimal representation but -128..127); any check for other values is useless here.
I think that here it tries to get the value of the pixel but in a range of 0 to 255, so it uses the mask 0xFF to delete all the bits in a higher position than 8.
But I don't understand why it uses
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
When the pix variable can't be higher than 255
How could you create a method that could flip 2 bits (ranges 00-11 Hence 0-3) in a byte, Randomly!
Example
Coin flip one: 111 01 111
Coin flip two: 111 11 111
Coin flip three: 111 01 111
Coin flip four: 111 10 111
What I'm working with
private static void coinFlip(byte theByte)
{
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
byte tmp = value & 255;
tmp = tmp >> 4;
tmp = tmp & 3;
//Point of confusion
//Now stuff it back in index 5 & 4 ?
}
Based on your code:
private static byte coinFlip(byte theByte)
{
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
return (byte)(theByte ^ (value << 3));
}
Last line is simply XORING your byte with the two shifted random bits.
Filling in using similar methods to what you are using, I think this should work:
private static byte coinFlip(byte theByte)
{
//Get random value of form 000xx000
Integer mode = new Random().nextInt(3);
byte value = mode.byteValue();
value = value << 3;
//Mask the result byte, to format xxx00xxx
byte mask = 231; //0b11100111
byte maskedByte = theByte & mask;
//return 000xx000 | xxx00xxx
return maskedByte | value;
}
As fge said, though, BitSet is the saner way to do it.
If you want to set a bit at index n, use:
b |= 1 << n;
if you want to unset a bit at index n, use:
b &= ~(1 << n);
Or use a BitSet (which has a convenient enough .flip() method).
I've got this loop that is run thousands of times (so needs to be efficient). It changes the value of the bitmap pixel.
I want to be able to run thought the loop and "switch" a certain group of pixels to alpha and then switch them back at a later point.
My question is.
How do I switch the values? So say 0xFFCC1BE0 becomes 0x00CC1BE0 and then if I want to switch back to 0xFFCC1BE0 I simply take the 00 and turn it too FF.
I can't make two bitmaps as I run out of memory :-(
Anyhow here's what I've got so far:
private void setTransparencyOnLightMap(float WidthPercentage, float LeftPosition)
{
int blankPixel = 0x00000000;
int savedPixel = 0x00000000;
int desiredAlpha = 200; //Can also be 0x00
//Find away of turning alhpa off and on.
for(int BMx = 0; BMx < mLightMap.getWidth(); BMx++)
{
for(int BMy = 0; BMy < mLightMap.getHeight(); BMy++)
{
if(mLightMap.getPixel(BMx, BMy) != blankPixel) //Make sure don't overwrite blank transparent pixels.
{
savedPixel = mLightMap.getPixel(BMx,BMy);
savedPixel = savedPixel | (desiredAlpha << 24);
mLightMap.setPixel(BMx, BMy, savedPixel);
}
}
}
}
You could switch the alpha of a pixel like so:
savedPixel = savedPixel & 0x00FFFFFF;
savedPixel = savedPixel | (desiredAlpha << 24);
The first line zeros out the 8 most significant bits of savedPixel (these are the bits where the alpha is held). The second line sets the 8 most significant bits of savedPixel to desiredAlpha. Note that desiredAlpha must be between 0 and 255 (These are the ints that can be stored in 8 bits).
Note that this uses bitwise operators, (&, |, <<) which are very efficient.
It seems to me, to reduce memory use, you can just save the original Alpha value of each pixel rather than the whole ARGB value - to do this use a byte array which will be 1/4 the size of the original bitmap. Also use a bit-mask for the new Alpha so you can use bitwise AND (&) as described by Tristan Hull...
byte[] savedAlphaArray = new byte[mLightMap.getWidth(), mLightMap.getHeight()];
int desiredAlphaMask = 0x00FFFFFF;
int pixel;
Then to save the Alpha values and apply the bit-mask do the following...
for (int i = 0; i < mLightMap.getWidth(); i++) {
for (int j = 0; j < mLightMap.getHeight(); j++) {
pixel = mLightMap.getPixel(i, j);
savedAlphaArray[i, j] = (pixel & 0xFF000000) >> 24;
mLightMap.setPixel(i, j, desiredAlphaMask & pixel);
}
}
To 'switch' back do the following...
for (int i = 0; i < mLightMap.getWidth(); i++) {
for (int j = 0; j < mLightMap.getHeight(); j++) {
pixel = mLightMap.getPixel(i, j);
mLightMap.setPixel(i, j, savedAlphaArray[i, j] << 24 & pixel);
}
}
I am trying to get the RGB value of any given pixel on an image into 12 bit binary, with each channel represented by 4 bits. For example, if a pixel has it's red channel at '255', or in binary "11111111". I wish to convert that to "1111".
I have got a code working, but it is rather slow, and I am wondering if there is a better way to do this.
Here's what i did.
I use the method getRGB(x, y) to get the RGB value of one pixel.
e.g. -4278864
I convert that into 3 separate channels e.g. r 190 g 181 b 176
I divide that by 16 to get integer equivalent of 4 bit
representation
I convert the number to a binary.
Add 0's in front of the binary if the binary generated is less
than 4 bit.
Concatenate to a 12bit binary to represent 12bit color output. e.g. 101110111011
Here are my code:
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class LoadImageApp extends Component {
private static int[] rgbArray;
private static double bitPerColor = 4.0;
public static void main(String[] args) {
BufferedImage img = null;
String fileName = "Image.jpg";
try {
//Read in new image file
img = ImageIO.read(new File("src/"+fileName));
}
catch (IOException e){
}
if (img == null) {
System.out.println("No image loaded");
}
else {
//Get RGB Value
int val = img.getRGB(500, 500);
System.out.println("rgbValue from getRGB is: " + val);
//Convert to three separate channels
int a = (0xff000000 & val) >>> 24;
int r = (0x00ff0000 & val) >> 16;
int g = (0x0000ff00 & val) >> 8;
int b = (0x000000ff & val);
System.out.println("rgbValue in RGB is: ");
System.out.println("a " + a + " r " + r + " g " + g + " b " + b);
double power = Math.pow(2.0, bitPerColor);
//Convert each channel to binary
String r4bit = Integer.toBinaryString((int)(r/(power)));
String g4bit = Integer.toBinaryString((int)(g/(power)));
String b4bit = Integer.toBinaryString((int)(b/(power)));
//Convert concatonate 0's in front to get desired bit count
int rDifference = (int)bitPerColor - r4bit.length();
int gDifference = (int)bitPerColor - g4bit.length();
int bDifference = (int)bitPerColor - b4bit.length();
for (int i = rDifference; i > 0; i--){
r4bit="0"+r4bit;}
for (int i = gDifference; i > 0; i--){
g4bit = "0"+g4bit;}
for (int i = bDifference; i > 0; i--){
b4bit = "0"+b4bit;}
//Concatonate three channel together to form one binary
String rgbValue = r4bit + g4bit + b4bit;
System.out.println("rgbValue in binary is: " + rgbValue);
}
}
}
It all works fine as as desired. However it's just really, really ugly, and slow, 2-3 seconds just to read one pixel. I was hoping to use the code to read a section of an image at a time, but i can imaging it taking AGES.
So any help would be very much appreciated.
Thanks in advance.
Your original code (in hex) is 0x00rrggbb. You want to convert this to 0x00000rgb. This will do it:
int rgb24 = ....;
int rgb12 = (rgb24 & 0x00f00000) >> 12 +
(rgb24 & 0x0000f000) >> 8 +
(rgb24 & 0x000000f0) >> 4;
If you wanted to "round" to the nearest color instead of truncating you could do this:
int r = (rgb24 & 0x00ff0000);
int g = (rgb24 & 0x0000ff00);
int b = (rgb24 & 0x000000ff);
r += (r >= 0x00f00000) ? 0x00080000 : 0;
g += (g >= 0x0000f000) ? 0x00000800 : 0;
b += (b >= 0x000000f0) ? 0x00000008 : 0;
int rgb12 = (r & 0x00f00000) >> 12 + (g & 0x0000f000) >> 8 + (b & 0x000000f0) >> 4;
This rounds up but only if the high-order 4 bits are not already 1111 (when you would risk overflow).
There are a few things that might be slowing it down, such as...
Getting each pixel individually from the BufferedImage
Using Math.pow() and possibly Integer.toBinaryString(), multiple times in the loop
Using Strings all the way through, rather than numbers like int or short. If you want a String, maybe do a single conversion from short --> String at the end.
I would probably try to do something like this...
// Get all the pixels
int pixelCount = imageWidth*imageHeight;
int[] pixelArray = new int[pixelCount];
img.getRGB(0,0,imageWidth,imageHeight,pixelArray,0,1);
// For storing the 4-bit data
short[] convertedArray = new short[pixelCount];
// calculate the conversion factor a single time
double power = Math.pow(2.0, bitPerColor);
// Loop over the pixels
for (int p=0;p<pixelCount;p++){
int pixel = pixelArray[p];
// Convert into separate channels
int a = (0xff000000 & val) >>> 24;
int r = (0x00ff0000 & val) >> 16;
int g = (0x0000ff00 & val) >> 8;
int b = (0x000000ff & val);
// Convert to 4-bit
a /= power;
r /= power;
g /= power;
b /= power;
// Create the short for the pixel (4 channels * 4 bits = a 2-byte short)
short newPixel = (a & 0x0000000f) << 24 | (r & 0x0000000f) << 16 | (g & 0x0000000f) << 8 | (b & 0x0000000f);
convertedArray[p] = newPixel;
// If you want to have the value as a String, do it here.
String binary = Short.toBinaryString(newPixel);
}
Offhand, I noticed you used the String plus operator for appending. I know it's simple code but that takes some work when it is in a loop. The operator calls a constructor to execute its function.
How big is the loop anyway?
Instead of using the plus operator, perhaps use other classes like StringBuilder or a Java equivalent of it. Tell me which class you end up using.
Investigate by timing your code!
When you want to see your possible bottlenecks, look at LOOPS in a heap or stack first since there are potentially many code executions. This should be a coding rule somewhere...
Try it out & have fun. Pls vote for my answer. I need a badge and more points :-)
Tommy Kwee
The value I have collected in the RGB when set using SetRGB will it provide me an image of binary for where the area where the image is present is white and the area whre the image is absent is black ?