I'm writing a simple blur effect and have run into a problem I can't figure out.
I have an array of colors and I want to get an RGBA average for each channel to color a pixel. Here is the code:
import java.awt.image.BufferedImage; import java.awt.Color; public class BlurEffects { public static BufferedImage GaussianBlur(BufferedImage img, int clrAvgX, int clrAvgY) { //Create the image that will have the "blurred" pixels BufferedImage blurredImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); //This variable is used to get and assign the number of array elements for various arrays int numArrayElements; /*Get the number of array elements for the pixel matrix used to get a color channel average for each pixel of img */ numArrayElements = (((clrAvgX * 2) + 1) * ((clrAvgY * 2) + 1)); //Create the pixel matrix array used to get a color channel average for each pixel of img Color[] clrAvgArray; clrAvgArray = new Color[numArrayElements]; Color avgColor = new Color(0, 0, 0, 0); //Create x and y variables to loop through img int imgX; int imgY; //Create x and y variables to through the pixel matrix int arrX; int arrY; //Create x and y variables to track pixel matrix locations int getX; int getY; //Create a pixelMatrix index counter int ctr = 0; //Create a integers for getting and setting pixel colors int clr; int a; int r; int g; int b; int pixel; /*Loop through each pixel of img, get the pixel matrix average of any pixel that isn't empty and write it to the corresponding pixel of blurredImage */ for (imgY = 0; imgY <= (img.getHeight() - 1); imgY++) { for (imgX = 0; imgX <= (img.getWidth() - 1); imgX++) { //Reset the counter ctr = 0; /*Determine if the pixel at the x,y coordinates is empty If it isn't, get the pixel matrix average of any pixel that isn't empty and write it to the corresponding pixel of blurredImage */ //Loop through the color averaging pixel matrix //Top to bottom for (arrY = 0; arrY <= (clrAvgY * 2); arrY++) { //Left to right for (arrX = 0; arrX <= (clrAvgX * 2); arrX++) { getX = (imgX - clrAvgX) + arrX; getY = (imgY - clrAvgY) + arrY; //Make sure that getX and getY are in the bounds of the image. If not, zero out the ARGB values if ((getX < 0) || (getY < 0) || (getX > (img.getWidth() - 1)) || (getY > (img.getHeight() - 1))) { clrAvgArray[ctr] = new Color(0, 0, 0, 0); } else { clr = img.getRGB(getX, getY); a = (clr >> 24) & 0xff; r = (clr >> 16) & 0xff; g = (clr >> 8) & 0xff; b = clr & 0xff; clrAvgArray[ctr] = new Color(r, g, b, a); } //Get the pixel's average color avgColor = ColorAveraging.ColorAverageByArray(clrAvgArray); //Increment the counter ctr++; } } //Assign the colors to the channels a = avgColor.getAlpha(); r = avgColor.getRed(); g = avgColor.getGreen(); b = avgColor.getBlue(); //Bitshift and OR the color channels into the pixel pixel = (a<<24) | (r<<16) | (g<<8) | b; //Color the pixel blurredImage.setRGB(imgX, imgY, pixel); } } return blurredImage; } }
import java.awt.Color; public class ColorAveraging { public static Color ColorAverageByArray(Color colors[]) { Color myAvgColor = new Color(0, 0, 0, 0); int i; int sumA = 0; int sumR = 0; int sumG = 0; int sumB = 0; int avgA = 0; int avgR = 0; int avgG = 0; int avgB = 0; //Loop through the colors array and get a combined value for each channel for (i = 0; i < colors.length; i++) { sumA += colors[i].getAlpha(); sumR += colors[i].getRed(); sumG += colors[i].getGreen(); sumB += colors[i].getBlue(); } avgA = sumA / colors.length; avgR = sumR / colors.length; avgG = sumG / colors.length; avgB = sumB / colors.length; //Create the new color myAvgColor = new Color(avgR, avgG, avgB, avgA); //System.out.println("It seems to work!"); return myAvgColor; } }
The user passes an image to GaussianBlur along with an X and Y value. These values represent the width and height of a matrix of pixels that surround each pixel of the image. For example, if x=2 and y=2, then for each pixel of the image, there will be a 5x5 pixel matrix with the sampled pixel at the center. In otherwords, moving 2 pixels out around the sampled pixel. If x=1 and y=3, then the matrix would be 3x7, 1 pixel out in the x directions, 3 pixels out in the y directions.
Here is what I have verified:
There is definitely data in every element of the clrAvgArray when it is passed to ColorAverageByArray from GaussianBlur.
There is definitely data in colors[0] in ColorAverageByArray.
colors.length is correct. If, from GaussianBlur, x=2 and y=2, then colors.length is 25. If x=1 and y=3 then, colors.length is 21.
An exception error is thrown if an attempt is made to access any element of the colors[] array other than [0].
So I'm stuck at sumA += colors[i].getAlpha() as soon as i is 1. What I can't figure out is, what happened to the fully stocked array from the time it was passed to the time it is accessed?