public BufferedImage convolution(BufferedImage srcImage) {
// 平滑滤波器
float mask[] = new float[]{1.0f/16, 2.0f/16, 1.0f/16,
2.0f/16, 4.0f/16, 2.0f/16,
1.0f/16, 2.0f/16, 1.0f/16};
int width = srcImage.getWidth();
int height = srcImage.getHeight();
int srcRGBs[] = new int[width*height];
srcImage.getRGB(0, 0, width, height, srcRGBs, 0, width);
int paddedRGBs[] = new int[(width+4)*(height+4)];
int paddedIndex = 2 * (width+4) + 2;
for (int i = 0; i < height * width; i++) {
while ( 1 >= (paddedIndex % (width + 4)) ||
(paddedIndex % (width + 4)) >= (width + 2) )
paddedIndex++;
paddedRGBs[paddedIndex] = srcRGBs[i];
paddedIndex++;
}
// 对填充过后的RGB数组进行卷积操作
int rgb[] = new int[3]; // 存储RGB值
int rgbs[][] = new int[9][3]; // 存储滤波器中9个像素的RGB值
float frgb[] = new float[3]; // 滤波处理后的RGB
int newPaddedRGBs[] = new int[(width+4)*(height+4)];
for (int j = 1; j <= (height + 1); j++) {
for (int i = 1; i <= (width + 2); i++) {
// 获取滤波器覆盖的9个像素的每个像素的RGB值
rgbs[0] = decodeColor(paddedRGBs[(j-1)*(width+4)+i-1]);
rgbs[1] = decodeColor(paddedRGBs[(j-1)*(width+4)+i]);
rgbs[2] = decodeColor(paddedRGBs[(j-1)*(width+4)+i+1]);
rgbs[3] = decodeColor(paddedRGBs[(j)*(width+4)+i-1]);
rgbs[4] = decodeColor(paddedRGBs[(j)*(width+4)+i]);
rgbs[5] = decodeColor(paddedRGBs[(j)*(width+4)+i+1]);
rgbs[6] = decodeColor(paddedRGBs[(j+1)*(width+4)+i-1]);
rgbs[7] = decodeColor(paddedRGBs[(j+1)*(width+4)+i]);
rgbs[8] = decodeColor(paddedRGBs[(j+1)*(width+4)+i+1]);
// 对于每个像素分别将RGB值乘以滤波器中的系数
for (int k = 0; k < 9; k++) {
frgb[0] += mask[k] * rgbs[k][0];
frgb[1] += mask[k] * rgbs[k][1];
frgb[2] += mask[k] * rgbs[k][2];
}
// 将滤波处理后的RGB值存到一个整型数组中
rgb[0] = (int)frgb[0];
rgb[0] = rgb[0] < 0 ? 0 : rgb[0];
rgb[0] = rgb[0] > 255 ? 255 : rgb[0];
rgb[1] = (int)frgb[1];
rgb[1] = rgb[1] < 0 ? 0 : rgb[1];
rgb[1] = rgb[1] > 255 ? 255 : rgb[1];
rgb[2] = (int)frgb[2];
rgb[2] = rgb[2] < 0 ? 0 : rgb[2];
rgb[2] = rgb[2] > 255 ? 255 : rgb[2];
newPaddedRGBs[(j)*(width+4)+i] = encodeColor(rgb);
}
}
BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 裁剪newRGBs数组到rgbArray
int rgbArray[] = new int[width*height];
paddedIndex = 2 * (width+4) + 2;
for (int i = 0; i < width * height; i++) {
while ( 1 >= (paddedIndex % (width + 4)) ||
(paddedIndex % (width + 4)) >= (width + 2) )
paddedIndex++;
rgbArray[i] = newPaddedRGBs[paddedIndex];
paddedIndex++;
}
destImage.setRGB(0, 0, width, height, rgbArray, 0, width);
return destImage;
}
上面的代码输出的结果是一副空白的图像,原因是存在一些bug。
int rgb[] = new int[3]; // 存储RGB值
int rgbs[][] = new int[9][3]; // 存储滤波器中9个像素的RGB值
float frgb[] = new float[3]; // 滤波处理后的RGB
上面的三行代码声明在了卷积操作的for循环以外,这导致对每个像素进行卷积运算时这三个变量其中都遗留下了上一次运算的结果,也就是没有初始化。
所以在进行了一部分运算之后,frgb中的值累加超过了255,这样导致以后的像素RGB值全部为255。
所以这三个变量应该声明在for循环之内,这样才能保证每一次使用时都是全新的,初始化了的变量。