I am trying to implement a Mean/Average 3x3 filter in Android using Bitmaps.
The application keeps on shutting down everytime I try to apply this filter. The error I get ArrayIndexOutOfBoundsException when I try to apply this filter on an image.
My code is as follows:
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = 0;
for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {
A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
B = pixels[x+filterX+width*(y+filterY)] & 0xFF;
}
}
}
}
You don't show the stack trace (edit: now you do, thanks), which would indicate which line is throwing the exception.
However at first glance it appears your issue is here:
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = 0;
for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {
A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
B = pixels[x+filterX+width*(y+filterY)] & 0xFF;
...
}
}
}
}
You are going beyond the bounds of the pixels array because you are attempting to apply a 3x3 filter directly to the edge of the image, and so the filter goes outside the image bounds. Consider your very first iteration:
And then you try and access pixels[x+filterX+width*(y+filterY)]
:
So you can see, accessing pixels[-1 + -width]
is clearly out of bounds. The same would happen at the upper bounds, if your filterX/filterY loop were correct (see note at bottom of this answer -- at the moment with your size of 3, filterX and filterY stop at 0, not 1).
You will either need to not apply the filter within filterWidth/2 (or filterHeight/2 vertically) pixels from the edge, or you will need to do some bounds checking when reading the image pixels and treat areas beyond the edge as 0.
One possible optimization is to create a filterWidth/2 (or filterHeight/2 vertically) black border around your image, and don't process those pixels near the edge. Then you don't need branches for bounds checking.
By the way, for odd sized filters, you'll need to do <= filterWidth / 2
(same for height) in your loop:
for (int filterX = -filterWidth / 2; filterX <= filterWidth / 2; filterX++) {
for (int filterY = -filterHeight / 2; filterY <= filterHeight / 2; filterY++) {
That will work for all odd sized filters.