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

AWT/Swing Java Discussion :

Optimisation - Techniques d'animation par pixels


Sujet :

AWT/Swing Java

  1. #1
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut Optimisation - Techniques d'animation par pixels
    Bonjour,

    Voila, j'ai construit une applet (Swing) qui affiche une animation et je me pose 2 questions paske je trouve que ca rame un peu :

    **********
    La premiere :
    **********

    Chaque image de l'animation est une image "rendue" par un petit moteur, c'est à dire que je calcule chaque pixel de l'image à partir de plein de parametres...

    Donc, j'ai fait un tableau d'int : buffer[hauteur*largeur] qui contient tout les pixels de l'image.

    Les pixels sont calculés dans un thread.

    J'ai declaré un MemoryImageSource qui prend sa source dans le buffer.

    Lors du paintComponent, je fait un bête g.drawImage(source)

    Y-a-t-il mieux pour afficher à l'ecran un tableau de pixels ?
    Une autre technique que le MemoryImageSource ?


    **********
    La seconde :
    **********

    Pour faire evoluer les parametres de mon animation, j'ai essayé avec un thread, qui fait une pause de 40ms entre chaque boucle, et j'ai essayé avec un timer, appelé toutes les 40ms

    Donc logiquement, si j'incremente de 1 un parametre de l'animation à chaque mise à jour, je devrais avoir 25 incrementations par seconde (1000/40)

    Or, des fois j'ai 15, des fois j'ai 30....

    Est-ce le timer ou le thread qui n'est pas stable ?

    Ou je m'y prend mal ?

    (je precise que à chaque appel de la mise à jour des parametres, il n'y a que quelques additions, rien de lourd qui ferait ralentir tout ca, et c'est dans un thread separé du reste...)


    Merci !

  2. #2
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Pour l'image il vaut mieux utiliser les BufferedImage et les WritableRaster, qui permettent d'avoir une image accélérée par le matériel.

    En ce qui concerne l'animation, tu as raison : le Timer et le Thread ne sont pas justes. Le timing n'est pas garanti par ces classes (d'ailleurs dans un OS non temps réel...). La solution est en fait assez simple. Utilise un Timer et, à chaque fois que tu reçois un "tick", calcule combien de temps s'est écoulé depuis le début de l'animation, puis calcule tes paramètres de dessin à l'aide de ça.

    J'explique tout cela en détail dans mes présentations :

    - Filthy Rich Clients (http://www.jroller.com/page/gfx/?anc...tation_slides), slides uniquement
    - Desktop Java (http://java.developpez.tv/javadesktop-dec2005/), dans la section "FX Animation", slides + vidéo en français
    - Extreme GUI Makeover (http://developers.sun.com/learning/j...2005/desktop/), slides + track audio (cherche TS-3605 sur la page, puis clique sur View pour voir les slides avec le son, en anglais)

    Je te conseille *vivement* d'utiliser le Timing Framework présenté dans "Filthy Rich Clients" pour gérer tes animations.

  3. #3
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    La classe tes presentations !

    Et tres instructif, aussi...

    Deux autres questions :

    * peut-tu m'en dire un peu plus sur l'utilisation des writableRaster ? Ca ne me parait pas tres clair dans la doc de Java (tout ce que je veux, c'est un tableau de pixels où ecrire mon rendu)

    * J'ai vu dans la doc que System.currentTimeMillis() pouvait donner des resultats differents selon l'OS. En general (d'apres la doc) cela renvoit en unité de 10ms, ce qui a l'air d'etre le cas sur mon PC-Windows. Comment faire si on a besoin de plus de precision ?

    Merci !

  4. #4
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Je n'ai pas d'exemple de WritableRaster, mais il suffit d'appeler setPixel() ou setDataElements() quand tu en as obtenu un lié à la BufferedImage.

    Pour la résolution, elle est plus proche de 16ms sous Windows. Tu peux descendre à une précision de 2/3 ms en utilisant System.nanoTime(). Cela dit, pour une animation, 16ms suffisent (environ 60 fps).

  5. #5
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ok, ca commence a venir...

    Mais comment je fais pour envoyer tout en tableau de pixels à la fois, avec chaque pixel codé ARGB sur un int ?

    Parce que pour l'instant, je n'arrive à envoyer que des tableau de pixels avec les pixels codés sur :
    A : un int
    R : un int
    G : un int
    B : un int

    pourtant j'ai changé de modele de bufferedImage : testé avec TYPE_INT_ARGB et TYPE_4BYTE_ABGR

    En fait, je voudrais ne pas separer les différentes composantes du pixel...

    Merci !

  6. #6
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Au fait, ensuite le plus efficace dans le paintComponent, c'est de faire

    g.drawImage( (Image) imageSource,0,0,null)

    ou y'a mieux ?

  7. #7
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Pour écrire dans l'image sans réunir les composantes il faut utiliser un TYPE_3BGR par exemple mais je te le déconseille car l'image sera incompatible avec le matériel et l'affichage plus lent.

    Il faut plutôt utiliser des pixels codés en TYPE_ARGB (autrement dit pixel = A << 24 | R << 16 | G << 8 | B) ce qui est tout de même la pratique la plus courante. Ensuite il te suffira de faire un setDataElements(0, 0, largeurImage, hauteurImage, tableauDePixels).

    Si tes compostantes sont déjà toutes contenues dans un int alors il n'y a aucun problème.

  8. #8
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Ok ! Autant pour moi !

    C'est ce que j'ai testé en premier, mais ca marchait pas...

    J'avais du faire une co***rie puisque maintenant ca marche !

    Et puis ca m'arrange sacrement puisque c'est comme ca que je calculait le rendu de mes images jusqu'a present...

    Merci pour tout !

  9. #9
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    Maintenant tout marche avec des bufferedImage, mais je n'ai pas gagné en vitesse...

    Apres quelques test, je suis pratiquement sur que la phase qui ralentit vraiment tout, c'est la copie du tableau de pixels vers l'ecran...

    Quel le plus efficace dans le paintComponent, c'est de faire

    g.drawImage( (Image) imageSource,0,0,null)

    ou y'a mieux ?

    Y-a-t-il d'autres optimisations possibles, en dehors du rendu ?

    Merci

  10. #10
    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
    Utiliser des BufferedImage compatible

    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
     
      static BufferedImage toCompatibleImage(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        int transparency = image.getTransparency();
        GraphicsConfiguration configuration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        BufferedImage result = configuration.createCompatibleImage(width, height, transparency);
        Graphics graphics = result.getGraphics();
        try {
          graphics.drawImage(image, 0, 0, null);
        }
        finally {
          graphics.dispose();
        }
        return result;
      }

  11. #11
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    merci, mais euh... j'avoue que j'ai pas compris grand chose...

    compatible entre quoi et quoi ?

    En fait, ma bufferedImage, je veux simplement l'afficher (rapidement) à l'ecran.

    Pour l'instant j'ai fait un derivé de JPanel, et dans paintComponent, je fait juste

    g.drawImage( (Image) maBufferedImage,0,0,null)

  12. #12
    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
    en fait cela permet de t'assurer de la compatibilité de ton image avec ta carte graphique.

    Fais une recherche sur "compatible BufferedImage" et tu verras un paquets de posts de Bouye ou Gfx qui en parlent

  13. #13
    Membre éclairé
    Avatar de buzzkaido
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2004
    Messages
    821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2004
    Messages : 821
    Points : 734
    Points
    734
    Par défaut
    merci

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

Discussions similaires

  1. optimisation animation par fps >60Hz
    Par Archimède dans le forum Débuter
    Réponses: 6
    Dernier message: 20/01/2010, 17h18
  2. Réponses: 2
    Dernier message: 26/07/2005, 21h44
  3. Modifier une image par pixels
    Par mateo.14 dans le forum MFC
    Réponses: 10
    Dernier message: 21/01/2005, 15h09
  4. [TImage] Transfert de Picture par pixels.
    Par H2D dans le forum Langage
    Réponses: 9
    Dernier message: 25/10/2003, 14h37
  5. [VB6] [Graphisme] Transfert d'image pixel par pixel
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 16
    Dernier message: 15/10/2002, 09h53

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