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 :

Graphics2D et filtres


Sujet :

2D Java

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 12
    Points : 7
    Points
    7
    Par défaut Graphics2D et filtres
    Bonjour à tous, je suis nouveau sur ces grands forums de developpez.com.

    J'ai une fenêtre JFrame

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    public class Client extends JFrame {
    ...

    Dans laquelle j'utilise le conteneur simple :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // # base du fenêtrage
            java.awt.Container c = getContentPane();
     
            // # scène de base
            stage = new Stage(this, 800, 600);
            c.add(stage, "Center");

    auquel j'ajoute un objet Stage qui est la base de ma plateforme graphique.
    Cette dernière consiste simplement en un arbre contenant des nodes graphiques.
    Puis ma fenêtre Client s'occupe, à chaque mise à jour graphique, de redessiner le tout (par récurrence, selon le pattern du visiteur).

    Maintenant où le problème apparaît - sans que vous ne sachiez toujours de quoi il s'agit -, c'est que j'utilise un double buffer et donc j'ai un objet BufferStrategy :

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // # système visuel
            // double buffering
            createBufferStrategy(2);
            strategy = getBufferStrategy();
            buffer = (Graphics2D)strategy.getDrawGraphics();

    Jusque là, pas de gros problème...
    Maintenant la mise à jour graphique :

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void paint(Graphics g) {
            // Nettoyage
            if(buffer == null) return;
            buffer.clearRect(0, 0, getWidth(), getHeight());
     
            // Nouvelle image
            stage.draw(new GraphicSession(buffer));
     
            // Affichage en double-buffering hardware
            strategy.show();
        }

    Mon problème se trouve en fait ailleurs...
    J'utilise ce système du visiteur via l'objet GraphicSession qui transmet le buffer Graphics2D à tous les enfants du stage.
    Ainsi chacun affiche son image par-dessus (et toutes les branches sont ordrées pour que l'ordre d'affichage soit correct).

    Mon problème, c'est que je voudrais pouvoir agir sur l'image complète.
    Je compte appliquer un filtre RescaleOp pour modifier la luminosité de la scène complète.

    Mais je n'ai pas accès à un objet BufferedImage... je n'ai accès qu'à l'objet Graphics2D.
    Comment puis-je m'y prendre pour appliquer un filtre sur l'image complète se trouvant dans l'objet buffer, double-buffer hardware ?

    Ma première idée est de réussir à faire une copie de ce qui se trouve dans le Graphics2D buffer, puis d'appliquer RescaleOp à cette copie puis de dessiner cette copie dans l'objet buffer.
    Mais y a-t-il un moyen de faire une copie de l'objet Graphics2D ?

    J'ai essayé de voir si on avait accès à l'image liée au buffer, mais ça se complique car il y a plusieurs types de BufferStrategy, et dans chaque cas il y a encore des tas de moyen de création des images de base... et je m'y perds surtout que je n'y ai pas accès vu que les propriétés de base des instances BufferStrategy sont ... protégées

    ---

    Suite à ce problème, je me demande en plus si mon idée d'utilisation de RescaleOp est la bonne.

    Je compte assombrir / éclaircir la scène complète. Est-ce la méthode la plus rapide ?
    Est-ce qu'appliquer une image transparente foncée par-dessus serait plus rapide ?

    La question devient importante dans le fait que je compte ajouter la possibilité d'avoir des zones isolées où l'assombrissement n'est pas le même, genre des endroits de lumière.

    Si je compte réaliser un assombrissement de la scène, tout en prenant compte de la possibilité d'avoir des zones (rondes) dont l'assombrissement sera modifié car éclairci, ai-je plutôt intérêt de m'y prendre autrement ?

    La méthode autre la plus simple que je vois est :

    - création d'une image foncée ayant la taille de ma scène, mais en transparence progressive = masque
    - je m'occuper de rendre transparentes les zones qui portent de la lumière ou même plutôt blanches
    - j'appliquer cette image à la scène
    => assombrissement des parties sombres sur le masque
    => les parties qui ont été supprimées sur le masque ne sont pas assombries
    => éclaircissement des parties blanchies sur le masque

    Est-ce une solution potentiellement utilisable en sachant que cette opération est faite très souvent ? Le fait de passer par des filtres (RescaleOp) est-il plus efficace ?

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Pour assombrir/éclaircir tes Graphics tu peux utiliser un simple AlphaComposite en SRC_OVER

    Dans ce genre:

    Code java : 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
     
    protected void paintComponent(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
     //.... dessin avant ...
     
     //Pour assombrir
      g2d.setPaint(Color.black);
     //Pour éclaircir: 
      g2d.setPaint(Color.white);
     
     //on affecte la trasnparence sur les prochains éléments dessinés sur les Graphics3d
     g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
     
     //On dessine une rectangle de la taille du composant
     g2d.draw(new Rectangle2D.double(0,0,getWidth(),getHeight());
     
    }
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Merci, c'est le moyen qui me paraît le plus facile à utiliser, mais est-ce le plus rapide et y en a-t-il d'autres ?
    Genre de passer par les filtres ?

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Bon, j'avance dans mon problème et maintenant je coince avec la transparence.

    Pour créer mon masque et l'appliquer, je fais :
    Code java : 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
    // Création du masque
            BufferedImage mask = gs.g2.getDeviceConfiguration()
                .createCompatibleImage(GraphicSession.width, GraphicSession.height);
            Graphics2D g2d = (Graphics2D)mask.createGraphics();
            // Transparence
            float alpha;
            boolean useLight = false;
            ....
            // Dessin
            g2d.drawRect(0, 0, GraphicSession.width, GraphicSession.height);
            // Affichage des lumières
            ...
            // Ancien système de transparence
            Composite lastComp = gs.g2.getComposite();
            // Transparence du masque
            gs.g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            // Application du masque
            gs.g2.drawImage(mask, null, 0, 0);
            // Remise à zéro de la transparence
            gs.g2.setComposite(lastComp);

    Si j'exclue l'affichage des lumières, il n'y a aucun problème, le masque fonctionne très bien et selon l'alpha je fais varier l'assombrissement.

    Mon problème se situe maintenant au niveau des lumières :

    Code java : 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
    // Affichage des lumières
    if(useLight){
                Iterator<LifeAnimator> it = Map.instance.personalIterator(LifeAnimator.class,
                        new DisplayParent.ValidityChecker<LifeAnimator>(){
                    public boolean verify(LifeAnimator life){
                        return life.light != LightSource.none;
                    }
                });
                g2d.setPaint(Color.white);
                // g2d.setComposite(AlphaComposite.Clear);
                while(it.hasNext()){
                    LifeAnimator life = it.next();
                    int w2 = life.light.size * Maps.casew;
                    int h2 = life.light.size * Maps.caseh;
                    g2d.fillOval(life.getAbsoluteBaseX() - w2, life.getAbsoluteBaseY() - h2, 2 * w2, 2 * h2);
                    trace("? " + life.getIdentifier() + " > " + life.light.name());
                }
            }

    Deux problèmes :
    - la lumière n'est pas correcte car il n'y a pas de dégradé
    - la lumière est un éclaircissement alors que ça devrait être une réduction de l'assombrissement dans mon cas

    Comment, à la place d'utiliser une couleur blanche, plutôt simuler un dégradé du noir jusqu'à la transparence complète ?
    Je voudrais créer un ovale dont les bords sont noirs, le centre est en transparence complète, et l'intérieur est un dégradé jusqu'à cette valeur.

    Pire, je voudrais que ça remplace les parties noires de l'image sur laquelle je travaille.

    Il semblerait que pour cela je doive utiliser AlphaComposite.Clear vu qu'il remplace littéralement les valeurs, cependant cela ne fonctionne pas :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    g2d.setPaint(new Color(0x00ffffff, true));
    g2d.setComposite(AlphaComposite.Clear);

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Dans ce cas, il va falloir passer par un GradientPaint spécifique (RadialGradientPaint) qui existe nativement dans java 6 ou dans la libraiire Batik pour les versions antérieures de java.

    Et dans ce RadialGradientPaint il te suffira d'utiliser une couleur transparente et du noir.

    Pour une couleur entièrement tranparente tu peux utiliser le constructeur de Color possédant 4 paramètres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Color c = new Color(255,255,255,255);
    Pour pour la RadialGradientPaint, bah je te laisse viser la doc:
    http://java.sun.com/javase/6/docs/ap...ientPaint.html
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Merci beaucoup, ça fonctionne tip top

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 845
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 845
    Points : 22 857
    Points
    22 857
    Billets dans le blog
    51
    Par défaut
    Dernierement je cherchais des composites plus avancees pour mes tests sur ma propre classe de Painter (inspires de ceux de SwingX). Je cherchais nottament une composite permettant de faire l'effet "dodge" et je suis tombe sur ca http://www.jhlabs.com/ et nottament la class MiscComposite qui contient egalement une composite permettant de faire l'effet "darken". Manque de bol, moi quand j'essaie, ca plante mais il me semble qu'il a indique sur son site qu'il utilisait le modele de couleur RGBA ou que ca tournait sur Mac... snif...
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

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

Discussions similaires

  1. Algorithme d'un filtre ?
    Par Vince78 dans le forum Algorithmes et structures de données
    Réponses: 17
    Dernier message: 04/09/2002, 15h54
  2. recherche filtre flou gaussien
    Par gimlithedwarf dans le forum Langage
    Réponses: 4
    Dernier message: 01/08/2002, 22h32
  3. TADOTable et filtre
    Par GaL dans le forum C++Builder
    Réponses: 16
    Dernier message: 02/07/2002, 16h52
  4. Filtre passe Bande
    Par Mau dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 28/06/2002, 17h03
  5. Probleme de filtre dans bdd
    Par scorpiwolf dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/06/2002, 10h43

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