How to set the particular value to any pixel in java? - java

Actually I'm working on some image processing project and got struck somewhere. I have to convert the colored image to grey scale and for this i have extracted the values of RED, GREEN, BLUE component of a pixel using GETRGB() n now I want to set the RGB value of that pixel equal to the average of its RGB component. The RGB components are stored in INT variables respectively, so can u help me to set the average of this RGB components to the original pixel value??
The part of the code is :
rgbArray=new int[w*h];
buffer.getRGB(0, 0, width, height, rgbArray , 0,width );
int a,r,g,b;
for(int i = 0 ; i<w*h; i++)
{
r = (0x00ff0000 & rgbArray[i]) >> 16;
g = (0x0000ff00 & rgbArray[i]) >> 8;
b = (0x000000ff & rgbArray[i]);
rgbArray[i] = (r+g+b)/3;
}
buffer.setRGB(0, 0, width, height, rgbArray , 0,width);
but this is not giving me a grey image. Can u tell where i am doing a mistake.

It is not clear what you want to do. If you are trying to produce a gray color I suggest referring to the following page: http://www.tayloredmktg.com/rgb/ which shows rgb codes for different shades of gray.
If you are trying to get a translucent image you have to use the alpha channel (RGBA commands) in java. You can also get translucency by compositing the underlying image with your current image in special ways but that is MUCH harder than using alpha channel.

Your code does not pack the grayscale level back into each color component. Also, as I said in my comment to the question, conversion to grayscale needs to consider the human eye's sensitivity to each color component. A typical formula for obtaining the gray level is
G = 0.30 * R + 0.59 * G + 0.11 * B
as this Wikipedia article states.
So your for loop should look like this:
for(int i = 0 ; i<w*h; i++)
{
a = (0xff000000 & rgbArray[i]);
r = (0x00ff0000 & rgbArray[i]) >> 16;
g = (0x0000ff00 & rgbArray[i]) >> 8;
b = (0x000000ff & rgbArray[i]);
int gray = (int)(0.30 * r + 0.59 * g + 0.11 * b);
if ( gray < 0 ) gray = 0;
if ( gray > 255 ) gray = 255;
rgbArray[i] = a | ( gray << 16 ) | ( gray << 8 ) | gray;
}
You can, of course, declare gray outside of the loop, like you did with r, etc.

Related

Alpha channel ignored when using ImageIO.read()

I'm currently having an issue with alpha channels when reading PNG files with ImageIO.read(...)
fileInputStream = new FileInputStream(path);
BufferedImage image = ImageIO.read(fileInputStream);
//Just copying data into an integer array
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, width, height, pixels, 0, width);
However, when trying to read values from the pixel array by bit shifting as seen below, the alpha channel is always returning -1
int a = (pixels[i] & 0xff000000) >> 24;
int r = (pixels[i] & 0xff0000) >> 16;
int g = (pixels[i] & 0xff00) >> 8;
int b = (pixels[i] & 0xff);
//a = -1, the other channels are fine
By Googling the problem I understand that the BufferedImage type needs to be defined as below to allow for the alpha channel to work:
BufferedImage image = new BufferedImage(width, height BufferedImage.TYPE_INT_ARGB);
But ImageIO.read(...) returns a BufferedImage without giving the option to specify the image type. So how can I do this?
Any help is much appreciated.
Thanks in advance
I think, your "int unpacking" code might be wrong.
I used (pixel >> 24) & 0xff (where pixel is the rgba value of a specific pixel) and it worked fine.
I compared this with the results of java.awt.Color and they worked fine.
I "stole" the "extraction" code directly from java.awt.Color, this is, yet another reason, I tend not to perform these operations this way, it's to easy to screw them up
And my awesome test code...
BufferedImage image = ImageIO.read(new File("BYO image"));
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = image.getRGB(x, y);
//value = 0xff000000 | rgba;
int a = (pixel >> 24) & 0xff;
Color color = new Color(pixel, true);
System.out.println(x + "x" + y + " = " + color.getAlpha() + "; " + a);
}
}
nb: Before some one tells that this is inefficient, I wasn't going for efficiency, I was going for quick to write
You may also want to have a look at How to convert get.rgb(x,y) integer pixel to Color(r,g,b,a) in Java?, which I also used to validate my results
I think the problem is that you're using arithmetic shift (>>) instead of logical shift (>>>). Thus 0xff000000 >> 24 becomes 0xffffffff (i.e. -1)

Image analysis function to calculate middle gray level (max(z)+min(z)/2 in Java

How do I calculate the middle gray level (max(z)+min(z)/2 over the points where the structuring element is 1 and sets the output pixel to that value?
I just know a little about how to get the RGB value each pixel by using image.getRGB(x,y). I have no idea how to get gray level value each pixel of the image and what is z in the formula and all that?
Please help me with this. Thanks in advance.
I'm going to assume that z are the pixels within your structuring element. I'm also going to assume that "structuring element" is in the case of morphology. Here are a few pointers before we start:
You can convert a colour pixel to its graylevel intensity by using the Luminance formula. By consulting the SMPTE Rec. 709 standard, the output graylevel intensity, given the RGB components is: Y = 0.2126*R + 0.7152*G + 0.0722*B.
We're going to assume that the structuring element is odd. This will allow for the symmetric analysis of the structuring element for each pixel in your image where it is placed
I'm going to assume that your image is already loaded in as a BufferedImage.
Your structuring element will be a 2D array of int.
I'm not going to process those pixels where the structuring element traverses out of bounds to make things easy.
As such, the basic algorithm is this:
For each pixel in our image, place the centre of the structuring element at this location
For each pixel location where the structuring element is 1 that coincides with this position, find the max and minimum graylevel intensity
Set the output image pixel at this location to be (max(z) + min(z)) / 2).
Without further ado:
public BufferedImage calculateMiddleGray(BufferedImage img, int[][] mask)
{
// Declare output image
BufferedImage outImg = new BufferedImage(img.getWidth(),
img.getHeight(), BufferedImage.TYPE_INT_RGB);
// For each pixel in our image...
for (int i = mask.length/2; i < img.getWidth() - mask.length/2; i++) {
for (int j = mask[0].length/2; j < img.getHeight() - mask[0].length/2; j++) {
int maxPix = -1;
int minPix = 256;
// For each pixel in the mask...
for (int x = -mask.length/2; x <= mask.length/2; x++) {
for (int y = -mask[0].length/2; y <= mask[0].length/2; y++) {
//Obtain structuring element pixel
int structPix = mask[y+mask.length/2][x+mask[0].length/2];
// If not 1, continue
if (structPix != 1)
continue;
// Get RGB pixel
int rgb = img.getRGB(i+x, j+y);
// Get red, green and blue channels individually
int redPixel = (rgb >> 16) & 0xFF;
int greenPixel = (rgb >> 8) & 0xFF;
int bluePixel = rgb & 0xFF;
// Convert to grayscale
// Performs SMPTE Rec. 709 lum. conversion using integer logic
int lum = (77*red + 150*green + 29*blue) >> 8;
// Find max and min appropriately
if (lum > maxPix)
maxPix = lum;
if (lum < minPix)
minPix = lum;
}
}
// Set output pixel
// Grayscale image has all of its RGB pixels equal
int outPixel = (maxPix + minPix) / 2;
// Cap output - Ensure we don't go out of bounds
if (outPixel > 255)
outPixel = 255;
if (outPixel < 0)
outPixel = 0;
int finalOut = (outPixel << 16) | (outPixel << 8) | outPixel;
outImg.setRGB(i, j, finalOut);
}
}
}
To call this method, create an image img using any standard method, then create a structuring element mask that is a 2D integer array. After, place this method in your class, then invoke the method by:
BufferedImage outImg = calculateMiddleGray(img, mask);
Also (and of course), make sure you import the necessary package for the BufferedImage class, or:
import java.awt.image.BufferedImage;
Note: This is untested code. Hope it works!

[Java-Opencv]: How convert an image from Cartesian space to Polar space?

Hi guys I have to convert this image:
in this:
in Java.
This is my code:
double Cx =original_img.width()/2;
double Cy =original_img.height()/2;
int rho,theta;
for (int i=0;i<img.getHeight();i++){
for(int j=0;j<img.getWidth();j++){
rho = (int)(Math.sqrt(Math.pow(i-Cx,2) + Math.pow(j-Cy,2)));
theta = (int)(Math.atan2((j-Cy),(i-Cx)));
int color;
try{
color = img.getRGB((int)rho, (int)theta);
}catch(Exception e){
color = 0;
}
int alpha = (color>>24) & 0xff;
int red = (color & 0x00ff0000) >> 16;
int green = (color & 0x0000ff00) >> 8;
int blue = color & 0x000000ff;
int pixel = (alpha << 24) | (red << 16) | (green << 8) | blue;
img2.setRGB(rho, theta, pixel);
System.out.println("point: "+rho+" "+theta);
}
}
What's wrong?
I haven't found a simple and good Log-Polar transform in java.
My steps are:
1) take an original image (original_img)
2) cycling on the rows and cols of image
3) calculate rho and theta (are the new X and Y coordinates for the new pixel, right?)
4) get color pixel at coords (rho,theta)
5) create new pixel and set at the new coords.
What miss or wrong?
Thank you.
Now I get it. You want to apply to pixel coordinates. Sorry.
rho = (int)(Math.sqrt(Math.pow(i-Cx,2) + Math.pow(j-Cy,2)));
theta = (int)(Math.atan2((j-Cy),(i-Cx)));
Why would you want int instead of double on the above code? If not required I would suggest use double. Also the code is wrong, you are subtracting the dimension each time. Do not do this:
rho = Math.sqrt(Math.pow(i,2) + Math.pow(j,2));
theta = Math.atan2((j),(i));
That looks fine to me. But why you want to convert to polar anyway?
P.S. The above code has noting to do with Opencv of course.
Edit: If I am interpreting correctly the algorithm you the Cartesian coordinates should be in the center of the image so use your code:
I cannot tell you about the rotation part though but from your statement get color pixel at coords (rho,theta) I am guessing that you don't have to rotate the image. The effect does not require this.

How to convert pixels to gray scale?

Ok, I am using Processing which allows me to access pixels of any image as int[]. What I now want to do is to convert the image to gray-scale. Each pixel has a structure as shown below:
...........PIXEL............
[red | green | blue | alpha]
<-8--><--8---><--8--><--8-->
Now, what transformations do I need to apply to individual RGB values to make the image gray-scale ??
What I mean is, how much do I add / subtract to make the image gray-scale ?
Update
I found a few methods here: http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/
For each pixel, the value for the red, green and blue channels should be their averages. Like this:
int red = pixel.R;
int green = pixel.G;
int blue = pixel.B;
pixel.R = pixel.G = pixel.B = (red + green + blue) / 3;
Since in your case the pixel colors seem to be stored in an array rather than in properties, your code could end up looking like:
int red = pixel[0];
int green = pixel[1];
int blue = pixel[2];
pixel[0] = pixel[1] = pixel[2] = (red + green + blue) / 3;
The general idea is that when you have a gray scale image, each pixel's color measures only the intensity of light at that point - and the way we perceive that is the average of the intensity for each color channel.
The following code loads an image and cycle through its pixels, changing the saturation to zero and keeping the same hue and brightness values.
PImage img;
void setup () {
colorMode(HSB, 100);
img = loadImage ("img.png");
size(img.width,img.height);
color sat = color (0,0,0);
img.loadPixels();
for (int i = 0; i < width * height; i++) {
img.pixels[i]=color (hue(img.pixels[i]), sat, brightness(img.pixels[i]));
}
img.updatePixels();
image(img,0,0);
}

How to replace colors in BufferedImage in JAVA

I'm wondering if there is a more efficient method for replacing colors in a BufferedImage. At the moment I use the following method:
I fill an array with colors to be replaced and the colors to replace them with, including transparency. Then I loop through every pixel in the image. If it matches one of the colors in the array I replace it with the new color from the array. Here is the code:
Graphics2D g2;
g2 = img.createGraphics();
int x, y, i,clr,red,green,blue;
for (x = 0; x < img.getWidth(); x++) {
for (y = 0; y < img.getHeight(); y++) {
// For each pixel in the image
// get the red, green and blue value
clr = img.getRGB(x, y);
red = (clr & 0x00ff0000) >> 16;
green = (clr & 0x0000ff00) >> 8;
blue = clr & 0x000000ff;
for (i = 1; i <= Arraycounter; i++) {
// for each entry in the array
// if the red, green and blue values of the pixels match the values in the array
// replace the pixels color with the new color from the array
if (red == Red[i] && green == Green[i] && blue == Blue[i])
{
g2.setComposite(Transparency[i]);
g2.setColor(NewColor[i]);
g2.fillRect(x, y, 1, 1);
}
}
}
The images I'm working with are small, 20x20 pixels or so. Nevertheless It seems there must be a more efficient way to do this.
Instead of changing the value of the image pixels you can modify the underlying ColorModel. Much faster that way and no need to iterate over the whole image so it scales well.
Use a HashMap<Color,Color>. The key should be the original color, and the value the replacement. If the get returns null, do nothing.
It looks like the idiomatic way to do this is to implement a LookupOp and then apply this operation to create a new target BufferedImage. There is a great answer here.
Have a look at BufferedImageFilter/BufferedImageOp to filter your image in the producer/consumer/observer paradigm.

Categories

Resources