Prima di tutto, sei inutilmente (e erroneamente) convertendo il tuo risultato da galleggiante a int ad ogni ciclo del ciclo. Tuo red
, green
e blue
dovrebbe essere di tipo galleggiante e dovrebbe essere restituito al numero intero solo dopo la convoluzione (quando viene convertito in 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);
Il sanguinamento dei colori nel tuo risultato è causato perché i tuoi coefficienti in matrix
sono sbagliati:
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f = 1.8452741
La somma dei coefficienti in una matrice di convoluzione offuscata dovrebbe essere 1.0. Quando si applica questa matrice a un'immagine, è possibile ottenere colori che sono più di 255. Quando ciò accade i canali "sanguinano" nel canale successivo (blu a verde, ecc.). Un'immagine completamente verde con questa matrice comporterebbe:
green = 255 * 1.8452741 ~= 471 = 0x01D7; rgb = 0xFF01D700;
Il che è un verde meno intenso con un pizzico di rosso.
Puoi risolverlo dividendo i coefficienti 1.8452741
, ma vuoi assicurarti che:
(int)(255.0f * (sum of coefficients)) = 255
In caso contrario, è necessario aggiungere un controllo che limita le dimensioni dei canali a 255 e non lasciarli in giro. Per esempio:
if (red > 255.0f)
red = 255.0f;
Per quanto riguarda l'efficienza/ottimizzazione:
Potrebbe essere che la differenza di velocità possa essere spiegata da questo inutile casting e chiamando Math.round, ma un candidato più probabile è il modo in cui si accede all'immagine. Non ho abbastanza familiarità con BufferedImage e Raster per consigliarti sul modo più efficiente per accedere al buffer di immagini sottostante.