En primer lugar, está convirtiendo innecesar (e injustamente) su resultado de Float a INT en cada ciclo del bucle. Su red
, green
y blue
debe ser de tipo flotante y debe devolverse a entero solo después de la convolución (cuando se convierte en RGB):
float red=0.0f, green = 0.0f, blue = 0.0f
for(int i = x;i<x+3;i++){
for(int j = y;j<y+3;j++){
int color = a.getRGB(i,j);
red += ((color >> 16) & 0xff)*matrix[(i-x)*3+j-y];
green += ((color >> 8) & 0xff)*matrix[(i-x)*3+j-y];
blue += ((color >> 0) & 0xff)*matrix[(i-x)*3+j-y];
}
}
return (a.getRGB(x, y)&0xFF000000) | (((int)red) << 16) | (((int)green) << 8) | ((int)blue);
El sangrado de los colores en su resultado es causado porque sus coeficientes en matrix
estan equivocados:
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f = 1.8452741
La suma de los coeficientes en una matriz de convolución borrosa debe ser 1.0. Cuando aplica esta matriz a una imagen, puede obtener colores superiores a 255. Cuando eso sucede, los canales "sangran" en el siguiente canal (azul a verde, etc.). Una imagen completamente verde con esta matriz daría como resultado:
green = 255 * 1.8452741 ~= 471 = 0x01D7; rgb = 0xFF01D700;
Que es un verde menos intenso con un toque de rojo.
Puedes arreglar eso dividiendo los coeficientes por 1.8452741
, pero quieres asegurarte de que:
(int)(255.0f * (sum of coefficients)) = 255
Si no, necesita agregar un cheque que limita el tamaño de los canales a 255 y no permita que se envuelvan. P.ej:
if (red > 255.0f)
red = 255.0f;
Con respecto a la eficiencia/optimización:
Podría ser que la diferencia en la velocidad puede explicarse por este innecesario casting y llamado Math.round, pero un candidato más probable es la forma en que está accediendo a la imagen. No estoy lo suficientemente familiarizado con BufferedImage y Raster para aconsejarle sobre la forma más eficiente de acceder al búfer de imagen subyacente.