Convert r,g,b value to one pixel value - java

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);

Related

Convert decimal to greyscale image in Java

I have a 2D array which contains values from 0-1.0 and my goal is to create an image where each element corresponds to a colour between white and black. Higher the value, the more white and vice versa.
So far I'm come up with the following Java code:
BufferedImage img = new BufferedImage(fg.getLengthInFrames(), 32 ,BufferedImage.TYPE_BYTE_GRAY);
for(int i =0; i < 32; i++) {
for(int j =0; j < fg.getLengthInFrames(); j++) {
colSTI.setRGB(j, i, 0); // wrong
}
}
Obviously this wont work as it is just a dummy function but say I had an array element, arr[0][5] = 0.85. How would I be able to convert this into a rgb value that is equal to the corresponding colour value?
Use TYPE_INT_ARGB image type (a color image supports gray scale no problem). Use
colSTI.setRGB(j, i, new Color(gray,gray,gray).getRGB());
to set the integer color value for the BufferedImage, here gray is you shade of gray int the range 0 .. 255. If the image is huge, to avoid creating and garbage collecting lots of Color objects, you can implement some kind of gray scale to color caching.
This approach supports 255 levels of gray only. You may need more complex approach if more levels are required. If you are representing some measured physical value in your image, I would propose to use color as well for representing different levels. Such false color images are common in science as they allow to see more levels easier.

Weird RGB value from java BufferedImage getRGB()

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

What type of array required in WritableRaster method setPixels()?

I don't understand how WritableRaster class of Java works. I tried looking at the documentation but don't understand how it takes values from an array of pixels. Plus, I am not sure what the array of pixels consists.
Here I explain.
What I want to do is : Shamir's Secret Sharing on images. For that I need to fetch an image in BuferedImage image. I take a secret image. Create shares by running a 'function' on each pixel of the image. (basically changing the pixel values by something)
Snippet:
int w = image.getWidth();
int h = image.getHeight();
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
int pixel = image.getRGB(j, i);
int red = (pixel >> 16) & 0xFF;
int green = (pixel >> 8) & 0xFF;
int blue = (pixel) & 0xFF;
pixels[j][i] = share1(red, green, blue);
// Now taking those rgb values. I change them using some function and return an int value. Something like this:
public int share1 (r, g, b)
{
a1 = rand.nextInt(primeNumber);
total1 = r+g+b+a1;
new_pixel = total1 % primeNumber;
return new_pixel;
}
// This 2d array pixels has all the new color values, right? But now I want to build an image using this new values. So what I did is.
First converted this pixels array to a list.
Now this list has pixel values of the new image. But to build an image using RasterObj.setPixels() method, I need an array with RGB values [I MIGHT BE WRONG HERE!]
So I take individual values of a list and find rgb values and put it consecutively in a new 1D array
pixelvector..something like this (r1,g1,b1,r2,g2,b2,r3,g3,b3...)
Size of the list is wh because it contains single pixel value of each pixel.
BUT, Size of the new array pixelvector will become wh*3 since it contains r,g,b values of each pixel..
Then to form image I do this: Snippet
BufferedImage image_share1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster rast = (WritableRaster) image_share1.getData();
rast.setPixels(0, 0, w, h, pixelvector);
image_share1.setData(rast);
ImageIO.write(image_share1,"JPG",new File("share1.jpg"));
If I put an array with just single pixel values in setPixels() method, it does not return from that function! But if I put an array with separate r,g,b values, it returns from the function. But doing the same thing for share1 , share 2 etc.. I am getting nothing but shades of blue. So, I am not even sure I will be able to reconstruct the image..
PS - This might look like a very foolish code I know. But I had just one day to do this and learn about images in Java. So I am doing the best I can.
Thanks..
A Raster (like WriteableRaster and its subclasses) consists of a SampleModel and a DataBuffer. The SampleModel describes the sample layout (is it pixel packed, pixel interleaved, band interleaved? how many bands? etc...) and dimensions, while the DataBuffer describes the actual storage (are the samples bytes, short, ints, signed or unsigned? single array or array per band? etc...).
For BufferedImage.TYPE_INT_RGB the samples will be pixel packed (all 3 R, G and B samples packed into a single int for each pixel), and data/transfer type DataBuffer.TYPE_INT.
Sorry for not answering your question regarding WritableRaster.setPixels(...) directly, but I don't think it's the method you are looking for (in most cases, it's not). :-)
For your goal, I think what you should do is something like:
// Pixels in TYPE_INT_RGB format
// (ie. 0xFFrrggbb, where rr is two bytes red, gg two bytes green etc)
int[] pixelvector = new int[w * h];
BufferedImage image_share1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster rast = image_share1.getRaster(); // Faster! No copy, and live updated
rast.setDataElements(0, 0, w, h, pixelvector);
// No need to call setData, as we modified image_share1 via it's raster
ImageIO.write(image_share1,"JPG",new File("share1.jpg"));
I'm assuming the rest of your code for modifying each pixel value is correct. :-)
But just a tip: You'll make it easier for yourself (and faster due to less conversion) if you use a 1D array instead of a 2D array. I.e.:
int[] pixels = new int[w * h]; // instead of int[][] pixels = new int[w][h];
// ...
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
// ...
pixels[y * w + x] = share1(red, green, blue); // instead of pixels[x][y];
}
}

How to get the pixel values of an image in the range 0-255 in android

I am trying to modify the image which I take it from the gallery in android. For modifying I need to get the pixel value of the image.
I do not want to differentiate the pixel value into R,G,B value. I want the pixel value as a single value
for (x = 0; x < w; x++){
for (y = 0;y < w; y++){
int pixels = bmpimg1.getPixel(x, y);
int alphavalue=Color.alpha(pixels);
int redValue = Color.red(pixels);
int blueValue = Color.blue(pixels);
int greenValue = Color.green(pixels);
totalvalue[x][y]=(redvalue+bluevalue+greenvalue)/3
}
}
//totalvalue=Assuming addition of redvalue, bluevalue,greenvalue and taking average will give me the pixel value in that location//
When I try to recreate the image using the totalvalue, I am not getting the image which i gave it as input.
I did the same in java using Raster.getpixels, when I tried to create the same image I am able to get the same image.
Bufferedimage img=ImageIO.read(new File("a.jpg");
Raster raster=img.getData();
for (int x=0;x<w;x++)
{
for(int y=0;y<h;y++)
{
pixels[x][y]=raster.getSample(x,y,0);
pixel[count++]=pixels[x][y];
}
}
When I create a new image using bufferedImage with the pixel[x][y], I am getting the original image
But in android, getpixel gives values in negative number
So how can i get the values of each pixel in the range 0-255 without separating into RGB value.
Kindly help me with this problem. Thank you
Since all red, blue and green component can take values up to 255, you can't just sum them to get a unic color value (since 1+2+3 = 2+3+1 for example)
you will have to store the color value in a number bigger than 255 with the method
color = redValue*2^16 + greenValue*2^8 + blueValue
You should be able to figure out how to retrieve red blue and green from this unique value
Good luck

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