Ok so I'm working on a program that takes in an image, isolates a block of pixels into an array, and then gets each individual rgb value for each pixel in that array.
When I do this
//first pic of image
//just a test
int pix = myImage.getRGB(0,0)
System.out.println(pix);
It spits out -16106634
I need to get the (R, G, B) value out of this int value
Is there a formula, alg, method?
The BufferedImage.getRGB(int x, int y) method always returns a pixel in the TYPE_INT_ARGB color model. So you just need to isolate the right bits for each color, like this:
int pix = myImage.getRGB(0, 0);
int r = (pix >> 16) & 0xFF;
int g = (pix >> 8) & 0xFF;
int b = pix & 0xFF;
If you happen to want the alpha component:
int a = (pix >> 24) & 0xFF;
Alternatively you can use the Color(int rgba, boolean hasalpha) constructor for convenience (at the cost of performance).
int pix = myImage.getRGB(0,0);
Color c = new Color(pix,true); // true for hasalpha
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
Related
So in a BufferedImage, you receive a single integer that has the RGB values represented in it. So far I use the following to get the RGB values from it:
// rgbs is an array of integers, every single integer represents the
// RGB values combined in some way
int r = (int) ((Math.pow(256,3) + rgbs[k]) / 65536);
int g = (int) (((Math.pow(256,3) + rgbs[k]) / 256 ) % 256 );
int b = (int) ((Math.pow(256,3) + rgbs[k]) % 256);
And so far, it works.
What I need to do is figure out how to get an integer so I can use BufferedImage.setRGB(), because that takes the same type of data it gave me.
I think the code is something like:
int rgb = red;
rgb = (rgb << 8) + green;
rgb = (rgb << 8) + blue;
Also, I believe you can get the individual values using:
int red = (rgb >> 16) & 0xFF;
int green = (rgb >> 8) & 0xFF;
int blue = rgb & 0xFF;
int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
If you know that your r, g, and b values are never > 255 or < 0 you don't need the &0x0ff
Additionaly
int red = (rgb>>16)&0x0ff;
int green=(rgb>>8) &0x0ff;
int blue= (rgb) &0x0ff;
No need for multipling.
if r, g, b = 3 integer values from 0 to 255 for each color
then
rgb = 65536 * r + 256 * g + b;
the single rgb value is the composite value of r,g,b combined for a total of 16777216 possible shades.
int rgb = new Color(r, g, b).getRGB();
To get individual colour values you can use Color like following for pixel(x,y).
import java.awt.Color;
import java.awt.image.BufferedImage;
Color c = new Color(buffOriginalImage.getRGB(x,y));
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
The above will give you the integer values of Red, Green and Blue in range of 0 to 255.
To set the values from RGB you can do so by:
Color myColour = new Color(red, green, blue);
int rgb = myColour.getRGB();
//Change the pixel at (x,y) ti rgb value
image.setRGB(x, y, rgb);
Please be advised that the above changes the value of a single pixel. So if you need to change the value entire image you may need to iterate over the image using two for loops.
I wanted to subtract two images pixel by pixel to check how much they are similar. Images have the same size one is little darker and beside brightness they don't differ. But I get those little dots in the result. Did I subtract those two images rigth? Both are bmp files.
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class Main2 {
public static void main(String[] args) throws Exception {
int[][][] ch = new int[4][4][4];
BufferedImage image1 = ImageIO.read(new File("1.bmp"));
BufferedImage image2 = ImageIO.read(new File("2.bmp"));
BufferedImage image3 = new BufferedImage(image1.getWidth(), image1.getHeight(), image1.getType());
int color;
for(int x = 0; x < image1.getWidth(); x++)
for(int y = 0; y < image1.getHeight(); y++) {
color = Math.abs(image2.getRGB(x, y) - image1.getRGB(x, y));
image3.setRGB(x, y, color);
}
ImageIO.write(image3, "bmp", new File("image.bmp"));
}
}
Image 1
Image 2
Result
The problem here is that you can't subtract the colors direcly. Each pixel is represented by one int value. This int value consists of 4 bytes. These 4 bytes represent the color components ARGB, where
A = Alpha
R = Red
G = Green
B = Blue
(Alpha is the opacity of the pixel, and always 255 (that is, the maximum value) in BMP images).
Thus, one pixel may be represented by
(255, 0, 254, 0)
When you subtract another pixel from this one, like (255, 0, 255, 0), then the third byte will underflow: It would become -1. But since this is part of ONE integer, the resulting color will be something like
(255, 0, 254, 0) -
(255, 0, 255, 0) =
(255, 255, 255, 0)
and thus, be far from what you would expect in this case.
The key point is that you have to split your color into the A,R,G and B components, and perform the computation on these components. In the most general form, it may be implemented like this:
int argb0 = image0.getRGB(x, y);
int argb1 = image1.getRGB(x, y);
int a0 = (argb0 >> 24) & 0xFF;
int r0 = (argb0 >> 16) & 0xFF;
int g0 = (argb0 >> 8) & 0xFF;
int b0 = (argb0 ) & 0xFF;
int a1 = (argb1 >> 24) & 0xFF;
int r1 = (argb1 >> 16) & 0xFF;
int g1 = (argb1 >> 8) & 0xFF;
int b1 = (argb1 ) & 0xFF;
int aDiff = Math.abs(a1 - a0);
int rDiff = Math.abs(r1 - r0);
int gDiff = Math.abs(g1 - g0);
int bDiff = Math.abs(b1 - b0);
int diff =
(aDiff << 24) | (rDiff << 16) | (gDiff << 8) | bDiff;
result.setRGB(x, y, diff);
Since these are grayscale images, the computations done here are somewhat redundant: For grayscale images, the R, G and B components are always equal. And since the opacity is always 255, it does not have to be treated explicitly here. So for your particular case, it should be sufficient to simplify this to
int argb0 = image0.getRGB(x, y);
int argb1 = image1.getRGB(x, y);
// Here the 'b' stands for 'blue' as well
// as for 'brightness' :-)
int b0 = argb0 & 0xFF;
int b1 = argb1 & 0xFF;
int bDiff = Math.abs(b1 - b0);
int diff =
(255 << 24) | (bDiff << 16) | (bDiff << 8) | bDiff;
result.setRGB(x, y, diff);
You did not "subtract one pixel from the other" correctly. getRGB returns "an integer pixel in the default RGB color model (TYPE_INT_ARGB)". What you are seeing is an "overflow" from one byte into the next, and thus from one color into the next.
Suppose you have colors 804020 - 404120 -- this is 3FFF00; the difference in the G component, 1 gets output as FF.
The correct procedure is to split the return value from getRGB into separate red, green, and blue, subtract each one, make sure they fit into unsigned bytes again (I guess your Math.abs is okay) and then write out a reconstructed new RGB value.
I found this which does what you want. It does seem to do the same thing and it may be more "correct" than your code. I assume it's possible to extract the source code.
http://tutorial.simplecv.org/en/latest/examples/image-math.html
/Fredrik Wahlgren
i had to convert from rgb to hsb so as to perform histogram equalization on an image. I have converted it back into rgb and i am getting a negative value like -158435. Can anyone please help me understand how to convert this into a colour so i can set it to my pixel? Thanks
Simply make use of the bit-shifting. It works.
int rgb = 0x00F15D49;
int r = (rgb >>> 16) & 0xFF;
int g = (rgb >>> 8) & 0xFF;
int b = rgb & 0xFF;
Then use this method
Color.RGBtoHSB(int r, int g, int b, float[] hsbvals); like this:
float[] hsb = Color.RGBtoHSB(r, g, b, null);
To convert it back, simply use the other method (edited, you were right):
int rgb = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
System.out.println(Integer.toHexString(rgb));
The negative value appears because you are storing colors as ARGB (Alpha Red Green Blue).
The alpha channel is then often just 100% opaque, which is 255 = 0xFF.
Therefore, when the color is converted to an 32 bit int, it appears negative.
Example: Opaque Black = ARGB(255, 0, 0, 0) = 0xFF000000 = -16777216
So in a BufferedImage, you receive a single integer that has the RGB values represented in it. So far I use the following to get the RGB values from it:
// rgbs is an array of integers, every single integer represents the
// RGB values combined in some way
int r = (int) ((Math.pow(256,3) + rgbs[k]) / 65536);
int g = (int) (((Math.pow(256,3) + rgbs[k]) / 256 ) % 256 );
int b = (int) ((Math.pow(256,3) + rgbs[k]) % 256);
And so far, it works.
What I need to do is figure out how to get an integer so I can use BufferedImage.setRGB(), because that takes the same type of data it gave me.
I think the code is something like:
int rgb = red;
rgb = (rgb << 8) + green;
rgb = (rgb << 8) + blue;
Also, I believe you can get the individual values using:
int red = (rgb >> 16) & 0xFF;
int green = (rgb >> 8) & 0xFF;
int blue = rgb & 0xFF;
int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
If you know that your r, g, and b values are never > 255 or < 0 you don't need the &0x0ff
Additionaly
int red = (rgb>>16)&0x0ff;
int green=(rgb>>8) &0x0ff;
int blue= (rgb) &0x0ff;
No need for multipling.
if r, g, b = 3 integer values from 0 to 255 for each color
then
rgb = 65536 * r + 256 * g + b;
the single rgb value is the composite value of r,g,b combined for a total of 16777216 possible shades.
int rgb = new Color(r, g, b).getRGB();
To get individual colour values you can use Color like following for pixel(x,y).
import java.awt.Color;
import java.awt.image.BufferedImage;
Color c = new Color(buffOriginalImage.getRGB(x,y));
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
The above will give you the integer values of Red, Green and Blue in range of 0 to 255.
To set the values from RGB you can do so by:
Color myColour = new Color(red, green, blue);
int rgb = myColour.getRGB();
//Change the pixel at (x,y) ti rgb value
image.setRGB(x, y, rgb);
Please be advised that the above changes the value of a single pixel. So if you need to change the value entire image you may need to iterate over the image using two for loops.
I obtain pixel color by
int color = image.getRGB(x,y);
then i want to acquire red, green, blue components separately. How to do that? Maybe using some bitmask?
int green = color&0x00ff00;
apparently not working... :(
To get color components you can use:
import android.graphics.Color;
int r = Color.red(intColor);
int g = Color.green(intColor);
int b = Color.blue(intColor);
int a = Color.alpha(intColor);
int value = image.getRGB(x,y);
R = (byte)(value & 0x000000FF);
G = (byte)((value & 0x0000FF00) >> 8);
B = (byte)((value & 0x00FF0000) >> 16);
A = (byte)((value & 0xFF000000) >> 24);
May need to flip the R, A, or B around.
You forgot to shift the byte to the right:
int green = (color & 0x00ff00) >> 8;
You can use Color constructor and pass the given integer and hasalpha=true:
Color color = new Color(image.getRGB(x,y), true);
getRGB returns the color of type TYPE_INT_ARGB which means it has an alpha channel.