2014-05-15 3 views
0

Je dois activer/désactiver les canaux RVB d'une image, mais je suis coincé et mon code est bogué.Basculer entre les canaux RVB

Pouvez-vous m'aider à trouver la bonne façon? Ceci est mon code:

Les canaux de fonction est appelée lorsque 1 de 3 cases à cocher a changé son état et fournit les arguments qui sont true == selected

public void channels(boolean red, boolean green, boolean blue) { 
    if (this.img != null) {// checks if the image is set 
     char r = 0xFF, g = 0xFF, b = 0xFF; 
     if (red == false) { 
      r = 0x00; 
     } 
     if (green == false) { 
      g = 0x00; 
     } 
     if (blue == false) { 
      b = 0x00; 
     } 
     BufferedImage tmp = new BufferedImage(
       img.getWidth(), 
       img.getHeight(), 
       BufferedImage.TYPE_INT_RGB); 
     for (int i = 0; i < img.getWidth(); i++) { 
      for (int j = 0; j < img.getHeight(); j++) { 
       int rgb = img.getRGB(i, j); 
       int red = (rgb >> 16) & r; 
       int green = (rgb >> 8) & g; 
       int blue = (rgb >> 0) & b; 
       int gbr = (red << 16) | (green << 8) | blue;// EDITED 
       tmp.setRGB(i, j, gbr); 
      } 
     } 
     img = tmp; 
     repaint(); 
    } else { 
     //show error 
    } 
} 

Merci pour votre aide!

+0

semble bon à première vue, que se passe-t-il réellement maintenant quand vous éteignez une chaîne? – Octopus

+2

Il semble que vous vous trompez de bits. Cela ne devrait pas être: 'int gbr = (red << 16) | (vert << 8) | bleu? Vous voulez essentiellement revenir dans le même ordre que la façon dont vous vous êtes décalé pour commencer ... non? Laissez-moi savoir si cela fonctionne. Si c'est le cas, je vais transformer cela en une réponse que vous pouvez accepter! :) – rayryeng

+0

lorsque j'éteins une chaîne, c'est OK, mais quand j'essaie d'allumer/éteindre d'autres chaînes, ça devient très salissant. Par exemple je ne peux pas éteindre puis sur un canal et obtenir la même image – Mark

Répondre

1

Il semble que vous vous trompez dans les bits. Ne devrait-il pas être: int gbr = (red << 16) | (green << 8) | blue;? En gros, vous voulez revenir dans le même ordre que la façon dont vous vous êtes décalé pour commencer.

De même, une fois que vous avez effacé la couleur correspondante, vous n'avez aucun moyen de la récupérer. Vous devrez stocker une copie de l'image originale quelque part. Quand il est temps de rallumer la chaîne, copiez simplement le pixel original de l'image originale.

En supposant que l'image d'origine est stockée quelque part comme origImg, je modifierais votre boucle for de sorte que si le canal est activé, copiez à partir de l'image originale.

for (int i = 0; i < img.getWidth(); i++) { 
    for (int j = 0; j < img.getHeight(); j++) { 
     int rgb = img.getRGB(i, j); 
     int origRGB = origImg.getRGB(i, j);    
     int redPixel = red ? (origRGB >> 16) & r : (rgb >> 16) & r; 
     int greenPixel = green ? (origRGB >> 8) & g : (rgb >> 8) & g; 
     int bluePixel = blue ? origRGB & b : rgb & b; 
     int gbr = (redPixel << 16) | (greenPixel << 8) | bluePixel; 
     tmp.setRGB(i, j, gbr); 
    } 
} 
2

Que diriez-vous de cette version optimisée, avec beaucoup moins de changement de bit?

public void channels(boolean showRed, boolean showGreen, boolean showBlue) { 
    if (this.origImg!= null) {// checks if the image is set 
     int channelMask = 0xff << 24 | (showRed ? 0xff : 0) << 16 | (showGreen ? 0xff : 0) << 8 | (showBlue ? 0xff : 0); 

     BufferedImage tmp = new BufferedImage(origImg.getWidth(), origImg.getHeight(), BufferedImage.TYPE_INT_RGB); 

     for (int i = 0; i < origImg.getWidth(); i++) { 
      for (int j = 0; j < origImg.getHeight(); j++) { 
       int rgb = origImg.getRGB(i, j); 
       tmp.setRGB(i, j, rgb & channelMask); 
      } 
     } 

     img = tmp; 
     repaint(); 
    } else { 
     //show error 
    } 
} 

Une approche encore plus rapide, serait probablement d'utiliser un canalisé Raster, ou tout au moins une configuration Raster qui permet de sous-échantillonnage de la bande (voir méthode Raster.createChild(...), en particulier le dernier paramètre).

LookupOp, comme mentionné par @trashgod est également une bonne idée, et probablement plus rapide que l'approche getRGB()/setRGB().

+0

+1 Mieux que ce que j'ai suggéré. Va te montrer combien d'expérience Java j'ai :) – rayryeng