package pl.vgtworld.imagedraw.filters.grayscale;

import java.awt.image.BufferedImage;

import pl.vgtworld.imagedraw.ImageDrawEntity;
import pl.vgtworld.imagedraw.filters.ImageDrawFilter;

public class GrayscaleFilter implements ImageDrawFilter {
	
	private static final int MAX_PIXEL_BRIGHTNESS = 255;
	
	private static final int RED_BIT_OFFSET = 16;
	
	private static final int GREEN_BIT_OFFSET = 8;
	
	private static final int COLOR_MASK = 0xFF;
	
	private float red;
	
	private float green;
	
	private float blue;
	
	public GrayscaleFilter() {
		red = 0.33f;
		green = 0.33f;
		blue = 0.33f;
	}
	
	public GrayscaleFilter(float red, float green, float blue) {
		if (red < 0 || red > 1 || green < 0 || green > 1 || blue < 0 || blue > 1) {
			throw new IllegalArgumentException("Each channel value must be between 0 and 1.");
		}
		this.red = red;
		this.blue = blue;
		this.green = green;
	}
	
	@Override
	public void doFilter(ImageDrawEntity image, int x, int y, int width, int height) {
		BufferedImage imageData = image.getImage();
		for (int i = x; i < x + width; ++i) {
			for (int j = y; j < y + height; ++j) {
				int pixelBrightness = calculatePixelBrightness(imageData.getRGB(i, j));
				imageData.setRGB(i, j, convertBrightnessToColor(pixelBrightness));
			}
		}
	}
	
	private int convertBrightnessToColor(int brightness) {
		return brightness + (brightness << 8) + (brightness << 16);
	}
	
	private int calculatePixelBrightness(int rgb) {
		int pixelRed = (rgb >> RED_BIT_OFFSET) & COLOR_MASK;
		int pixelGreen = (rgb >> GREEN_BIT_OFFSET) & COLOR_MASK;
		int pixelBlue = rgb & COLOR_MASK;
		float brightness = pixelRed * red + pixelGreen * green + pixelBlue * blue;
		int roundedBrightness = (int) brightness;
		if (roundedBrightness > MAX_PIXEL_BRIGHTNESS) {
			return MAX_PIXEL_BRIGHTNESS;
		}
		return roundedBrightness;
	}
}

@@ -182,16 +182,77 @@
 ilter;%0A%0A
+/**%0A * Filter converting image to its grayscale version.%0A */%0A
 public c
@@ -579,87 +579,674 @@
 %0A%09%0A%09
-public GrayscaleFilter() %7B%0A%09%09red = 0.33f;%0A%09%09green = 0.33f;%0A%09%09blue = 0.33f;%0A%09%7D%0A%09
+/**%0A%09 * Creates filter with default configuration.%0A%09 * %0A%09 * %3Cp%3E%0A%09 * Each RGB channel is used at the same strength, when converting image to%0A%09 * grayscale.%0A%09 */%0A%09public GrayscaleFilter() %7B%0A%09%09red = 0.33f;%0A%09%09green = 0.33f;%0A%09%09blue = 0.33f;%0A%09%7D%0A%09%0A%09/**%0A%09 * Creates filter with custom configuration.%0A%09 * %0A%09 * %3Cp%3E%0A%09 * Each RGB channel can have defined strength, when converting image to%0A%09 * grayscale. Strength for each channel must be between 0 and 1.%0A%09 * %0A%09 * @param red%0A%09 *           Red channel strength during convertion.%0A%09 * @param green%0A%09 *           Green channel strength during convertion.%0A%09 * @param blue%0A%09 *           Blue channel strength during convertion.%0A%09 */
 %0A%09pu
@@ -2481,10 +2481,12 @@
 ess;%0A%09%7D%0A
+%09%0A
 %7D%0A

Add documentation for class and constructors.