2015-03-04 5 views
1

Je me demande si le GraphicsContext d'un Canvas dans JavaFX peut remplacer tous les pixels d'un chemin de manière à ce qu'ils redeviennent transparents. Comme la fonction clearRect mais pour n'importe quel chemin.Remplacer le chemin par des couleurs transparentes dans javafx Canvas/GraphicsContext

J'ai regardé les différents BlendModes et effets, mais il semble que il n'y a pas moyen de passer outre en fait la valeur alpha qui pourrait être réalisé par exemple

  • rendu une couleur transparente avec l'opérateur Porter/Duff Src
  • rendu une couleur non transparente destination sur globalCompositeOperation en HTML5

Je serais très heureux si quelqu'un connaissait un moyen d'y parvenir sans tessellation le chemin et l'utilisation de plusieurs appels clearRect. Je vous remercie.

http://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/GraphicsContext.html


addition en réponse au premier commentaire: Au lieu d'utiliser un nœud de chemin que je utilise un nœud Canvas pour effectuer le rendu en utilisant le GraphicsContext et donc, il est impossible de modifier le couleur d'un chemin précédemment rendu. Je suis en train de faire quelque chose comme

Canvas canvas = …; 
final GraphicsContext context = canvas.getGraphicsContext(); 
context.setFill(Color.BLUE); 
context.fillRect(0,0,100,100); 
… 
… 

et plus tard je veux rétablir les pixels dans un chemin vers la transparence

context.setStroke(Color.TRANSPARENT); 
context.beginPath(); 
context.moveTo(0, 0); 
context.lineTo(10,10); 
… 
context.stroke(); 

Cependant, le mélange est appliqué cela ne fonctionne pas. Dans d'autres bibliothèques de rendu, il est possible d'utiliser par ex. l'une des méthodes de mélange/composition mentionnées ci-dessus pour y parvenir mais jusqu'à présent, je n'étais pas capable d'identifier une telle fonctionnalité dans javafx.

+0

Soit vous avez le noeud Path et définissez l'opacité ou vous ne le faites pas et vous redessinez le chemin avec la couleur d'arrière-plan. – Roland

+0

J'ai édité la question avec plus de détails pour essayer de clarifier les questions – illfang

+0

Mais à quoi s'attendre lorsque vous peignez sur la toile avec une couleur transparente? Cela n'aura aucun effet. Il suffit de le peindre avec la couleur de fond. Je soupçonne que ce que tu veux, ce sont des couches différentes. Ce n'est pas ce qu'est un seul Canvas. – Roland

Répondre

1

Je n'ai pas trouvé de mécanisme pour effacer une toile en fonction d'un chemin. Mais voici comment vous pouvez le faire manuellement:

  • Créer un masque sur lequel vous dessinez le chemin
  • image Blend et le masque manuellement

Exemple avec un rectangle bleu qui a été appliqué un masque avec un chemin:

public class ManualBlendWithMask extends Application { 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) { 

     Group root = new Group(); 

     // create canvas 
     Canvas canvas = new Canvas(200, 200); 
     canvas.setTranslateX(100); 
     canvas.setTranslateY(100); 

     // create canvas with blue rectangle 
     GraphicsContext canvasGC = canvas.getGraphicsContext2D(); 
     canvasGC.setFill(Color.BLUE); 
     canvasGC.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); 

     // create mask 
     Canvas mask = new Canvas(canvas.getWidth(), canvas.getHeight()); 
     GraphicsContext maskGC = mask.getGraphicsContext2D(); 
     maskGC.setFill(Color.WHITE); 
     maskGC.fillRect(0, 0, mask.getWidth(), mask.getHeight()); 

     // draw path 
     maskGC.setStroke(Color.BLACK); 
     maskGC.setLineWidth(20); 
     maskGC.beginPath(); 
     maskGC.moveTo(0, 0); 
     maskGC.lineTo(400, 400); 
     maskGC.stroke(); 

     // get image from canvas 
     WritableImage srcImage = new WritableImage((int) canvas.getWidth(), (int) canvas.getHeight()); 
     srcImage = canvas.snapshot(null, srcImage); 

     // get image from mask 
     WritableImage srcMask = new WritableImage((int) mask.getWidth(), (int) mask.getHeight()); 
     srcMask = mask.snapshot(null, srcMask); 

     PixelReader maskReader = srcMask.getPixelReader(); 
     PixelReader imageReader = srcImage.getPixelReader(); 

     int width = (int) srcMask.getWidth(); 
     int height = (int) srcMask.getHeight(); 

     // create dest image 
     WritableImage dest = new WritableImage(width, height); 
     PixelWriter writer = dest.getPixelWriter(); 

     // blend image and mask 
     for (int x = 0; x < width; x++) { 
      for (int y = 0; y < height; y++) { 

       Color maskColor = maskReader.getColor(x, y); 
       Color imageColor = imageReader.getColor(x, y); 

       if (maskColor.equals(Color.WHITE)) { 
        writer.setColor(x, y, imageColor); 
       } 

      } 
     } 

     // clear canvas and fill it with the blended image 
     canvasGC = canvas.getGraphicsContext2D(); 
     canvasGC.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 
     canvasGC.drawImage(dest, 0, 0); 

     // draw background with gradient 
     Rectangle rect = new Rectangle(400, 400); 
     rect.setFill(new LinearGradient(0, 0, 1, 1, true, CycleMethod.REFLECT, new Stop(0, Color.RED), new Stop(1, Color.YELLOW))); 

     // show nodes 
     root.getChildren().addAll(rect, canvas); 

     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 

    } 

} 

Bien sûr, il serait préférable que quelqu'un puisse trouver un exemple en utilisant BlendModes. Qu'est-ce que vous aimeriez réaliser, à quoi ressemble-t-il dans un exemple d'image? enter image description here

+0

Merci pour votre réponse détaillée. Comme votre réponse a montré une approche différente de la résolution du problème, j'accepterai votre réponse, car il semble que personne ne connaisse un moyen de l'implémenter avec BlendModes ou des techniques similaires qui nécessiteraient sûrement moins de ressources. Je vous remercie. – illfang