2009-05-20 8 views
2

Je sais que possible de convertir une image en utilisant CS_GRAYJava Convertir ColorSpace de BufferedImage à CS_GRAY sans utiliser ConvertColorOp

public static BufferedImage getGrayBufferedImage(BufferedImage image) { 
    BufferedImageOp op = new ColorConvertOp(ColorSpace 
      .getInstance(ColorSpace.CS_GRAY), null); 
    BufferedImage sourceImgGray = op.filter(image, null); 

    return sourceImgGray; 
} 

cependant, c'est un goulot d'étranglement de mon programme. Je dois le faire souvent, sur des images de 800x600 pixels et prend environ 200-300ms pour que cette opération se termine, en moyenne. Je sais que je peux le faire beaucoup plus rapidement en utilisant une boucle pour faire une boucle dans les données de l'image et le régler tout de suite. D'autre part, le code ci-dessus construit une toute nouvelle image buffered 800x600 en échelle de gris. Je préfère simplement transformer l'image que je passe.

Est-ce que quelqu'un sait comment faire cela avec une boucle for et étant donné que l'image est l'espace colorimétrique RVB?

Répondre

2

ColorConvertOp.filter prend deux paramètres. Le second paramètre est également un BufferedImage, qui sera la destination. Si vous passez un BufferedImage correct à la méthode filter, il vous évite les tracas pour créer un nouveau BufferedImage.

1
private static int grayscale(int rgb) { 
    int r = rgb >> 16 & 0xff; 
    int g = rgb >> 8 & 0xff; 
    int b = rgb  & 0xff; 
    int cmax = Math.max(Math.max(r, g),b); 
    return (rgb & 0xFF000000) | (cmax << 16) | (cmax << 8) | cmax; 
} 
public static BufferedImage grayscale(BufferedImage bi) { 
    BufferedImage bout = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB); 
    int[] rgbArray = new int[bi.getWidth() * bi.getHeight()]; 
    rgbArray = bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), rgbArray, 0, bi.getWidth()); 
    for (int i = 0, q = rgbArray.length; i < q; i++) { 
     rgbArray[i] = grayscale(rgbArray[i]); 
    } 
    bout.setRGB(0, 0, bout.getWidth(), bout.getHeight(), rgbArray, 0, bout.getWidth()); 
    return bout; 
} 

Quoi que vous fassiez, vous faites probablement quelque chose de mal. Vous ne devriez pas régénérer une image mise en mémoire tampon encore et encore. Mais, plutôt de trouver un schéma pour simplement mettre à jour l'image tamponnée, ou prendre les pixels d'origine de l'original et en utilisant simplement l'échelle de gris qui est le maximum des composants RVB, dans chacune des sections.

Questions connexes