Image Blurring (Bitwise) problem

Hi everybody ;D
I’m not really new to the forum but that is the first time I’m posting something.
I have been working on a little project inspired by “Zen’a photo garden”,and I need to blur the image in that project. So I decided to learn how to do blurring. I’ve searched for the algorithm and I think I understand it. However I have a problem with the color channels. Here is my code:

public void blur(BufferedImage image) {
		//Note: the BufferedImage is of the type "INT_RGB"
		
		// set pixels
		int[] pixelData = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
		//Second array so pixels don't get overwritten while still needing them
		int[] pixels = pixelData.clone();
		
		//main loop over pixels
		for (int n = 0; n < pixelData.length; n++) {
			//Separate channels
			int r = 0, g = 0, b = 0;

			//loops to get neighbor pixels in the x direction
			for (int i = -1; i < 1; i++) {
				//discarding exceptions for the first and last pixels
				try {
					r += (pixelData[n + i] >> 16) & 0xff0000;
					g += (pixelData[n + i] >> 8) & 0x00ff00;
					b += (pixelData[n + i] >> 0) & 0x0000ff;
				} catch (ArrayIndexOutOfBoundsException e) {
					
				}
			}
			
			//averaging the colors of the pixels
			r /= (3);
			g /= (3);
			b /= (3);
			
			//final pixel
			pixels[n] = r | g | b;
		}
		
		//writing pixel data to the image
		image.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
	}

This is the method that I call to blur the image. As you can see (and I can’t :wink: ) there is a problem with it. It outputs different colors even when I’m using black and white. I believe the mistake is in the bitwise operations. I’ve tried various methids to get it to work but with no avail :frowning: .

If someone could explain to me what is wrong with my code and how can I solve it that would be great ;D

PS: I know that this method only takes neighboring pixels in the x direction, and I’m planning to make it take circular shaped neighboring. But that is just for demonstration.

For CPU blurring I would recommend Romain Guy’s box blur algorithm. It’s simple and fast enough, and also adjustable for different strengths.

Example:
http://www.java-gaming.org/?action=pastebin&id=612

For GPU blurring look here:

Your extraction of the color components as well as the composition of the final pixel are both wrong. They should look like this:


for (int i = -1; i < 1; i++) {
            //discarding exceptions for the first and last pixels
            try {
               int pix=pixelData[n + i];
               r += (pix >> 16) & 255;
               g += (pix >> 8) & 255;
               b += pix & 255;
            } catch (ArrayIndexOutOfBoundsException e) {
               
            }
         }
         
         //averaging the colors of the pixels
         r /= (3);
         g /= (3);
         b /= (3);
         
         //final pixel
         pixels[n] = (r<<16) | (g<<8) | b;

My god ! It works :smiley:
Thank you so much. However, what did we really do ? Why did we shift them first to the right and then to the left ? Why isn’t it the same ? I’m guessing that the shifting was just for the masking “&” to work correctly (?). Also, why did we mask with “0xff = 255” on all the channels ? I mean why didn’t we mask green with “0x00ff00” etc. ? Moreover the image kept getting darker when I blurred it, but that is something I think I can fix by myself. I know that’s alot of question but bear with me ::slight_smile:

You could as well mask them without shifting, but that makes clamping and working with the different color components much more complicated, because you would have to shift your other values instead (for example, if you want to add 128 to red, you would have to add 128<<16 instead). I prefer to shift them down to 8bit, so that all have the same range of values. That makes mixing them much easier too and it allows you to use the same algorithms on all components.

In your case, you had a mix of both methods, which doesn’t work. Shifting red to the right by 16 and then applying the mask leaves you with a black color.

Oh I finally understand :o
Thank you mate . That was very helpful :slight_smile: