Bonjour à tous,
Je développe une petite application de manipulation d'image en Java.
Dans un certain cas j'ai besoin de définir un "masque" par dessus une image. Le masque se dessine à la souris avec un gros pinceau (grossièrement) et s'affiche en transparence par dessus l'image.
On doit pouvoir modifier la couleur du masque si on en a envie (rouge par défaut).
Pour faire ça j'utilise une BufferedImage de type INT_ARGB que j'affiche par dessus l'image de base, j'appelle cette image "mask".
Pour dessiner dans mon masque j'ai le code suivant :
L'objet Cursor est un "Shape" que j'utilise pour déterminer la form du pinceau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 // get image graphics object final Graphics2D g = (Graphics2D) mask.getGraphics(); // set no alpha g.setComposite(AlphaComposite.Src); // set color depending "remove" or "add" to mask if (remove) g.setColor(new Color(0x00000000, true)); else g.setColor(new Color(0x80000000, true)); // draw cursor in the mask g.fill(cursor);
Ensuite pour l'affichage en temps que tel (image de base + le masque) j'utilise le code suivant :
Mon problème étant, comme vous l'avez peut être vu dans les commentaires du code, que la méthode "g2m.fillRect(...)" n'est pas assez rapide, elle devient même carrément lente sur de grosses images (5000 x 5000).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 public void paint(Graphics g) { // get graphics object of mask final Graphics2D g2m = (Graphics2D) mask.getGraphics(); // we want to use source alpha information to mix color g2m.setComposite(AlphaComposite.SrcIn); // set mask color g2m.setColor(getMaskColor()); // THIS IS SLOW ! g2m.fillRect(0, 0, mask.getWidth(), mask.getHeight()); final Graphics2D g2 = (Graphics2D) g; // draw base image g2.drawImage(image, null, 0, 0); // draw mask g2.drawImage(mask, null, 0, 0); }
Je n'arrive pas à comprendre pourquoi puisque si j'essaie de faire la même opération sur l'objet "g2" alors ça reste très rapide même sur de très large surface (10000 x 10000) ! Je sais que l'objet "g2" représente le contexte graphique actuel mais je pense que Java 6 est capable de délivrer des "BufferedImage" accélérés dans la plupart des cas (et surtout pour une image de type INT_ARGB). J'ai essayé les différents xxxGraphicsDevice.createCompatibleImage(...) ou même createVolatileImage(...) mais sans succés
Honnêtement je suis sûr qu'il y des bien meilleurs méthodes pour afficher un masque coloré en transparence sur une image mais pour le moment je n'ai pas trouvé J'ai essayé d'utiliser une image de type BYTE_GRAY qui contenait 0x00 (transparent) et 0xFF (non transparent) pour le masque afin de réduire la charge mémoire du masque (après tout 1 bit devrait suffire) mais avec ce type d'image je n'ai pas été capable d'afficher le masque correctement puisque la méthode "g2m.setComposite(AlphaComposite.SrcIn)" n'a de sens qu'avec une information de type alpha ! De plus impossible d'afficher le masque autrement qu'en niveau de gris
Mais je me dis que j'ai du louper quelque chose, il n'est pas normal de devoir déclarer une image INT_ARGB pour afficher un pauvre masque mono couleur avec un degré de transparence fixé ! théoriquement 1 bit suffit ... pourtant je ne vois pas comment m'en sortir sans passer par une fichue image ARGB à un moment donné.
Merci à tout ceux qui pourront me venir en aide. Le plus important ça serait déjà de pouvoir corriger mon problème de performance sur le "g2m.fillRect(...)", ensuite la méthode, c'est secondaire... même si la méthode actuelle ne me convient pas vraiment
Partager