2

I'm attempting to take a picture as input, then manipulate said picture (I specifically want to make it greyscale) and then output the new image. This is a snippet of the code that I'm editing in order to do so but I'm getting stuck. Any ideas of what I can change/do next. Greatly appreciated!

public boolean recieveFrame (Image frame) {
    int width = frame.width();
    int height = frame.height();

    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            Color c1 = frame.get(i, j);
            double greyScale = (double) ((Color.red *.3) + (Color.green *.59) + (Color.blue * .11));
            Color newGrey = Color.greyScale(greyScale);
            frame.set(i, j, newGrey);
        }
    }

    boolean shouldStop = displayImage(frame); 
    return  shouldStop;
}
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
NuNu
  • 667
  • 2
  • 12
  • 21
  • [How to desaturate an image](http://stackoverflow.com/questions/6471340/how-do-i-desaturate-a-bufferedimage-in-java/6471524#6471524) – mre Jan 23 '12 at 23:04

1 Answers1

0

I'm going to try to stick as close as possible to what you already have. So, I'll assume that you are looking for how to do pixel-level processing on an Image, rather than just looking for a technique that happens to work for converting to greyscale.

The first step is that you need the image to be a BufferedImage. This is what you get by default from ImageIO, but if you have some other type of image, you can create a BufferedImage and paint the other image into it first:

BufferedImage buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffer.createGraphics();
g.drawImage(image, 0, 0);
g.dispose()

Then, you can operate on the pixels like this:

public void makeGrey(BufferedImage image) {
   for(int x = 0; x < image.getWidth(); ++x) {
      for(int y = 0; y < image.getHeight(); ++y) {
         Color c1 = new Color(image.getRGB(x, y));
         int grey = (int)(c1.getRed() * 0.3 
                        + c1.getGreen() * 0.59 
                        + c1.getBlue() * .11
                        + .5);
         Color newGrey = new Color(grey, grey, grey);
         image.setRGB(x, y, newGrey.getRGB());
      }
   }
}

Note that this code is horribly slow. A much faster option is to extract all the pixels from the BufferedImage into an int[], operate on that, and then set it back into the image. This uses the other versions of the setRGB()/getRGB() methods that you'll find in the javadoc.

Russell Zahniser
  • 16,188
  • 39
  • 30
  • You can replace the floating-point arithmetic with scaled integer operations (eg, `grey = red*30 + green*59 + blue*11)/100`). Not sure if this is a big enough speed improvement, though. – David R Tribble Jan 24 '12 at 00:44
  • Wouldn't that lead to a `grey` value of >255 for `white`? How was that formula devised? – Andrew Thompson Jan 24 '12 at 02:25
  • @Andrew: Using the formula I gave, a pixel color of (255,255,255) will result in a gray value of 255. That formula is a popular one for converting color to grayscale based on human perception sensitivity (30% red + 59% green + 11% blue). – David R Tribble Jan 31 '12 at 20:57