Weird RGB value from java BufferedImage getRGB() - java

Im trying to get RGB value from a grayscale image and it was return wrong(?) RGB value. Here is the code.
Color color = new Color(image.getRGB(0, 0));
System.out.print(color.getRed());
System.out.print(color.getGreen());
System.out.print(color.getBlue());
At a color picker was using, the first pixel RGB value R:153,G:153,B:153 but my code print
203203203
Why this thing happened? And also, im trying to use MATLAB Grayscale values for the exact pixel is also 153. Am i doing this wrong?
this is the image

This is because image.getRGB(x, y) by definition returns ARGB values in sRGB colorspace.
From the JavaDoc:
Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace. Color conversion takes place if this default model does not match the image ColorModel.
Matlab and other tools likely use a linear RGB or gray color space, and this is why the values are different.
You can get the same values from Java if the image is gray scale (TYPE_BYTE_GRAY), by accessing the Raster and its getDataElements method.
Object pixel = raster.getDataElements(0, 0, null); // x, y, data array (initialized if null)
If the image is TYPE_BYTE_GRAY, pixel will be a byte array with a single element.
int grayValue = ((byte[]) pixel)[0] & 0xff;
This value will be 153 in your case.

Just try this
System.out.println(image.getRaster().getSample(0, 0, 0)); //R
System.out.println(image.getRaster().getSample(0, 0, 1)); //G
System.out.println(image.getRaster().getSample(0, 0, 2)); //B
Here getSample(int x, int y, int b) Returns the sample in a specified band for the pixel located at (x,y) as an int. [According to this]
Parameters:
x - The X coordinate of the pixel location
y - The Y coordinate of the pixel location
b - The band to return b = [0,1,2] for [R,G,B]
and also take a look at BufferedImage getRGB vs Raster getSample

Related

How to check if a pixel is black using image.getRGB(x, y)

Should I expect the color of the pixel to be black if
image.getRGB(x, y) returns 0?
My assumption: I would expect 0 because the bit values of each of the values (Red, Green, Blue) would be zero. Am I correct in thinking this?
No, BufferedImage#getRGB() returns hex number. See this unit test:
public class TestRgb {
#Test
public void testBlack(){
BufferedImage bufferedImage = new BufferedImage(1,1, TYPE_BYTE_BINARY);
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setPaint(new Color(0,0,0)); //black
graphics2D.fillRect(0,0,1,1);
// pass - alpha channel set by default, even on all black pixels
TestCase.assertTrue(bufferedImage.getRGB(0,0)==0xFF000000);
// pass - when looking at just the color values (last 24 bits) the value is 0
TestCase.assertTrue((bufferedImage.getRGB(0,0) & 0x00FFFFFF)==0);
// fail - see above
TestCase.assertTrue(bufferedImage.getRGB(0,0)==0);
}
}
"Returns the RGB value representing the color in the default sRGB ColorModel. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are =blue)."
That is, the packing (in hex locations) is as follows, where each component can have a value of 0 (0x00) .. 255 (0xFF).
AARRGGBB
Thus, the final value is not only dependent upon RGB, when all color components are zero:
AA000000
In fact, AA will be 0xFF ("100% opaque") by default unless it has explicitly been set to a different value in a buffer / model that supports an alpha channel.

Get RGB components from ColorModel

I want to extract the R,G and B values of the pixels of an image. I do it in two ways.
File img_file = new File("../foo.png");
BufferedImage img = ImageIO.read(img_file);
1st method(which works fine):
img.getRaster().getPixel(i, j, rgb);
2nd method(which throws new IllegalArgumentException("More than one component per pixel"))
red = img.getColorModel().getRed(img.getRGB(i, j));
What is the reason for this behaviour?
Normally when I want to extract RGB from a BufferedImage I do something like this:
File img_file = new File("../foo.png");
BufferedImage img = ImageIO.read(img_file);
Color color = new Color(img.getRGB(i,j));
int red = color.getRed();
Based on the JavaDocs
An IllegalArgumentException is thrown if pixel values for this
ColorModel are not conveniently representable as a single int
It would suggest that the underlying color model is representable by a single int value
You may also want to take a look at this answer for some more details
Typically, you would simply take the int packed pixel from the image and use Color to generate a Color representation and then extract the values from there...
First, get the int packed value of the pixel at x/y...
int pixel = img.getRGB(i, j);
Use this to construct a Color object...
Color color = new Color(pixel, true); // True if you care about the alpha value...
Extract the R, G, B values...
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
Now you could simply do some bit maths, but this is simpler and is more readable - IMHO

BufferedImage: Set all pixels white where alpha = 0

I have a BufferedImage and would like to set all pixels that are fully transparent to be fully-transparent white (rather than transparent blank, or whatever may be in the source file). I can of course loop through the entire image using getRGB and setRGB, but is there some other way that would be much faster?
You can set the pixels like this:
public void setRGB(int startX,
int startY,
int w,
int h,
int[] rgbArray,
int offset,
int scansize)
This method sets an array of integer pixels in the default RGB color model (TYPE_INT_ARGB) and default sRGB color space, into a portion of the image data. Color conversion takes place if the default model does not match the image ColorModel. There are only 8-bits of precision for each color component in the returned data when using this method. With a specified coordinate (x, y) in the this image, the ARGB pixel can be accessed in this way:
pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)];
I can't say for sure if it is faster, but take a look at the ColorConvertOp class.
I haven't used it personally, but it might be what you are looking for.

Convert r,g,b value to one pixel value

I am trying to access the pixels of image using method getRGB(). The image I use for this purose is 8-bit image i.e each pixel is represented by 8-bits, hence the possible values are 0-255.
the image I used was png 8-bit image hence the type 'type_byte_indexed'
if (type == BufferedImage.TYPE_BYTE_INDEXED) {
System.out.println("type.byte.indexed");
System.out.print(h+" "+w);
sourceImage.getRGB(0, 0, w, h, rgbs, 0, w); //rgbs is integer array
for (i = 0; i <10; i++) {
System.out.print(" "+rgbs[i]);
}
System.out.println("rgbs len: " + rgbs.length);
}
The output of the for loop is something ilke:
-12048344 -12174804 -12048344 -12174804 -12174804 .......
I obtain the r,g,b components from it and store in array :
Color c=new Color(rgbs[i]);
r=c.getRed();
g=c.getGreen();
b=c.getBlue();
Now how do I combine again these values so that I can use the setRGB method? Like for 24 bit image we can use
int rgb=65536*pixel[i]+256*pixel[i+1]+pixel[i+2];
The documentation clearly states that the returned values are in ARGB-form:
Returns an array of integer pixels in the default RGB color model (TYPE_INT_ARGB) and default sRGB color space
You can access the underlying buffer (that contains indexed pixels) with
byte[] data=((DataBufferByte)bufferedImage.getRaster().getDataBuffer()).getData(0);

How to get gray level each pixel of the image in java

there...
I have some question about my homework on image processing using java. My question :
how to get gray level value each pixel of the rgb image in java programming???
I just know a little about how to get rgb value each pixel by syntax image.getRGB(x,y) for return rgb value. I have no idea for to get gray level value each pixel of the image....
Thanks for advance
First you'll need to extract the red, green and blue values from each pixel that you get from image.getRGB(x, y). See this answer about that. Then read about converting color to grayscale.
I agree with the previous answer. Create the BufferedImage like BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY). From what I understand a raster is for reading pixel data and a writable raster for writing pixel data or updating pixels. I always use writable raster although this may not be the best way to do it, because you can read pixel data and set pixel values. You can get the raster by WritableRaster raster = image.getRaster(); you can then get the value of a pixel by using raster.getSample(x, y, 0); The 0 in the arguments is for the band you want to get which for gray scale images should be 0.
You could also set up a BufferedImage of type TYPE_BYTE_GRAY, and draw the picture into it, then get the raster data and find the values.
Complementing Daniel's answer:
WritableRaster wr = myBufferedImage.getRaster();
for(int i = 0; i < myBufferedImage.getWidth(); i++){
for(int j = 0; j < myBufferedImage.getHeight(); j++){
int grayLevelPixel = wr.getSample(i, j, 0);
wr.setSample(i, j, 0, grayLevelPixel); // Setting same gray level, will do nothing on the image, just to show how.
}
}

Categories