IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

2D Java Discussion :

Probleme de performance avec objet Graphics d'une image.


Sujet :

2D Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 68
    Par défaut Probleme de performance avec objet Graphics d'une image.
    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 :

    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);
    L'objet Cursor est un "Shape" que j'utilise pour déterminer la form du pinceau.

    Ensuite pour l'affichage en temps que tel (image de base + le masque) j'utilise le code suivant :

    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);
             }
    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).
    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

  2. #2
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Y-a-t'il une raison quelconque pour que tu redessines sur le masque à chaque repaint? Ne suffirait-il pas de faire ça simplement à chaque changement de couleur? Car les composites ont une certaines tendance à être relativement lourd niveau traitement.

    Secondement assures toi vraiment que tu as bien rendu tom image compatible, le gain en traitement est visible.

    Les VolatileImage sont des bestioles un tant soit peu récalcitrantes, cf JavaDoc, donc à éviter autant que peut se faire:

    Citation Envoyé par javadoc
    The drawing surface of an image (the memory where the image contents actually reside) can be lost or invalidated, causing the contents of that memory to go away. The drawing surface thus needs to be restored or recreated and the contents of that surface need to be re-rendered. VolatileImage provides an interface for allowing the user to detect these problems and fix them when they occur.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 68
    Par défaut
    Citation Envoyé par sinok Voir le message
    Y-a-t'il une raison quelconque pour que tu redessines sur le masque à chaque repaint? Ne suffirait-il pas de faire ça simplement à chaque changement de couleur? Car les composites ont une certaines tendance à être relativement lourd niveau traitement.

    Secondement assures toi vraiment que tu as bien rendu tom image compatible, le gain en traitement est visible.

    Les VolatileImage sont des bestioles un tant soit peu récalcitrantes, cf JavaDoc, donc à éviter autant que peut se faire:
    Merci pour ta réponse
    Disons que redessiner à chaque repaint est plus simple car mon getMaskColor() utilise "une formule" pour être calculé, l'état peut changer souvent, au final le problème de lenteur se posera à un autre moment mais sera tout aussi gênant... et puis naïvement je pensais que le rectFill() était très rapide, ce que je ne comprends pas c'est qu'il l'est quand je le fais sur l'objet Graphics renvoyé par la méthode paint()...

    Pour la compatibilité de mon image, j'ai essayé de passer par :
    GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(w, h, alpha);

    Ca me retourne une image INT_ARGB ce qui me parait normal puisque ça semble être le type "optimal" quand tu veux une composante alpha. Malgré tout ça reste aussi lent... j'ai essayé de modifier le AccelerationPriority mais ça ne change rien.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 68
    Par défaut
    J'ai fait quelque tests supplémentaire, si mon masque est une image INT_RGB (sans transparence donc) ou si je n'utilise pas la méthode setComposite alors effectivement l'affichage est plus rapide, MAIS ça reste bien plus lent que de dessiner dans l'objet Graphics global, un bête fillRect(0,0, 5000, 3000) prend environ 50ms (et j'ai une grosse config) alors que sur l'objet Graphics global ça prend environ 1ms Il y a donc bien un problème sur mon image qui n'est décidément pas accélérée...

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 68
    Par défaut
    Je me fais une raison, je crois que excepté via un VolatileImage (que je ne peux pas utiliser dans mon cas), les "offscreen buffers" sont lents quoiqu'il arrive en Java

    J'aimerai bien trouver une méthode plus intelligente pour rendre ce fichu masque

  6. #6
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Préparer ton masque dans un Thread et demander le repaint une fois la préparation finie (ie à la fin de l'exécution du Thread).

    En effet toute opération lente dans un paint est un gros problème puisque bloquant l'EDT, et de fait toute l'application.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. probleme de performance avec curseur
    Par donny dans le forum PL/SQL
    Réponses: 6
    Dernier message: 06/08/2009, 14h44
  2. [C#] objet graphics dans une bitmap
    Par lancer83 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 04/08/2006, 14h30
  3. Réponses: 14
    Dernier message: 09/08/2004, 13h42
  4. problemes de performances avec les requetes select
    Par berry dans le forum Requêtes
    Réponses: 3
    Dernier message: 10/07/2003, 13h39
  5. problemes de performances avec les requetes select
    Par berry dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 10/07/2003, 13h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo