Hi guys, I am trying to implement a real time box blur filter on a 640 x 480 screen. My strategy is doing 2 separate 1D blurs, blur pixels in horizontal direction in the first pass, then blur vertically in the second pass. So we effectively end up using a cross shaped kernel instead of the square shape (hence less pixels to be processed over all).
Below is my code, it works fine, result looks great, but i wonder if you guys can suggest anything which could further speed up the algorithm?
Thanks in advance!
public class BlurFilter {
//Blur filter set the value of each pixel to the average value of its neighboring pixels.
//the filter kernel used here has a cross shape instead of square, the size of the kernel depends on radius.
public static void filterPixels(int radius, int[] img, int[] offsSreenBuffer){
//blur image in horizontal direction then vertical direction
horizontalBlur(radius, img, offsSreenBuffer);
verticalBlur(radius, offsSreenBuffer, img);
//repeat for another time for better quality
horizontalBlur(radius, img, offsSreenBuffer);
verticalBlur(radius, offsSreenBuffer, img);
}
public static void horizontalBlur(int radius, int[] source, int[] dest){
int i,j,sourcePositoin, destPosition,rgb1, rgb2, tr, tg, tb, pixelCount;
for(i = 0; i < 480; i++){
sourcePositoin = i * 640;
destPosition = i + 480 * 639;
tr = 0; tg = 0; tb = 0;
for(j = 0; j <= radius; j++){
rgb1 = source[sourcePositoin + j];
tr+=((rgb1 & 0xff0000) >> 16);
tg+=((rgb1 & 0x00ff00) >> 8);
tb+=(rgb1 & 0xff);
}
pixelCount = radius + 1;
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
sourcePositoin++;
destPosition-=480;
pixelCount++;
for(j = 1; j <= radius; j++, sourcePositoin++, destPosition-=480, pixelCount++){
rgb1 = source[sourcePositoin + radius];
tr+=((rgb1 & 0xff0000) >> 16);
tg+=((rgb1 & 0x00ff00) >> 8);
tb+=(rgb1 & 0xff);
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
pixelCount--;
for(j = radius + 1; j < 640 - radius; j++, sourcePositoin++, destPosition-=480){
rgb1 = source[sourcePositoin + radius];
rgb2 = source[sourcePositoin - radius - 1];
tr+=(((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16);
tg+=(((rgb1 & 0x00ff00) - (rgb2 & 0x00ff00)) >> 8);
tb+=((rgb1 & 0xff) - (rgb2 & 0xff));
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
pixelCount--;
for(j = 640 - radius; j < 640; j++, sourcePositoin++, destPosition-=480, pixelCount--){
rgb2 = source[sourcePositoin - radius - 1];
tr-=((rgb2 & 0xff0000) >> 16);
tg-=((rgb2 & 0x00ff00) >> 8);
tb-=(rgb2 & 0xff);
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
}
}
public static void verticalBlur(int radius, int[] source, int[] dest){
int i,j,sourcePositoin, destPosition,rgb1, rgb2, tr, tg, tb, pixelCount;
for(i = 0; i < 640; i++){
sourcePositoin = i * 480;
destPosition = 639 -i;
tr = 0; tg = 0; tb = 0;
for(j = 0; j <= radius; j++){
rgb1 = source[sourcePositoin + j];
tr+=((rgb1 & 0xff0000) >> 16);
tg+=((rgb1 & 0x00ff00) >> 8);
tb+=(rgb1 & 0xff);
}
pixelCount = radius + 1;
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
sourcePositoin++;
destPosition+=640;
pixelCount++;
for(j = 1; j <= radius; j++, sourcePositoin++, destPosition+=640, pixelCount++){
rgb1 = source[sourcePositoin + radius];
tr+=((rgb1 & 0xff0000) >> 16);
tg+=((rgb1 & 0x00ff00) >> 8);
tb+=(rgb1 & 0xff);
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
pixelCount--;
for(j = radius + 1; j < 480 - radius; j++, sourcePositoin++, destPosition+=640){
rgb1 = source[sourcePositoin + radius];
rgb2 = source[sourcePositoin - radius - 1];
tr+=(((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16);
tg+=(((rgb1 & 0x00ff00) - (rgb2 & 0x00ff00)) >> 8);
tb+=((rgb1 & 0xff) - (rgb2 & 0xff));
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
pixelCount--;
for(j = 480 - radius; j < 480; j++, sourcePositoin++, destPosition+=640, pixelCount--){
rgb2 = source[sourcePositoin - radius - 1];
tr-=((rgb2 & 0xff0000) >> 16);
tg-=((rgb2 & 0x00ff00) >> 8);
tb-=(rgb2 & 0xff);
dest[destPosition] = ((tr/pixelCount)<<16)|((tg/pixelCount)<<8)|(tb/pixelCount);
}
}
}
}