Buffer d'images et affichage

Messages postés
4
Date d'inscription
vendredi 11 août 2006
Statut
Membre
Dernière intervention
17 août 2006
-
Messages postés
4
Date d'inscription
vendredi 11 août 2006
Statut
Membre
Dernière intervention
17 août 2006
-
Bonjour à tous


Voila mon problème:

Je dois afficher une série d'images à une fréquence déterminée (10images/sec).

Pour cela, j'ai créer 2 threads:

  -le premier rempli un buffer (taille fixée à 25 images pour des
raisons de mémoire) avec des images que j'ai pris le soin de charger
(MediaTracker)

  -le deuxième thread extrait une image du buffer et la transmet au canva en lui disant de la dessiner.(boucle avec la fréquence de rafraichissement)

Au début tout va bien mais au bout de quelques images, il y a
ralentissement de l'affichage vu que le buffer se vide plus vite qu'il
ne se remplie.


Voici un bout de code:

Le thread chargé de l'affichage:
public void run() {

    System.out.println("Début Afficheur");

    Image image=null;

    if(buffer==null){

        System.out.println("Buffer d'image non initialisé !");

        return;

    }

    while(makingVideo){

        if(isWaiting){

            //En pause

            continue;

        }

        image = buffer.getNextImage();

        if((image==null)&&(!bufferRunner.isAlive())){

            //Fin de la vidéo

            makingVideo = false;

            return;

        }

        canva.set_image(image);//L'image est transmise au canva puis déssinée

        for(int i=0;i<nbParam;i++){

            ((MyGraphicPanel)panelVector.elementAt(i)).goToNextPoint();

        }

        try {

            Thread.sleep(100);//Pour la vitesse de rafraichissement

        } catch (InterruptedException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

    buffer.killThread();//Arret du remplissage

    System.out.println("Fin Afficheur");

}


Le thread qui rempli le buffer:

(le buffer est en fait une LinkedList contenu dans une classe MyBuffer)

public void run() {

    // Le thread rempli sans cesse le buffer tant qu'il
y a des images et tant qu'il n'a pas atteint sa taille max

    while(indexLastImg+1=maxSize){

            //Buffer plein

            continue;

        }

        if(addImageToBuffer(indexLastImg+1)){//Ajout de l'image dans le buffer

            indexLastImg++;//L'ajout de l'image a réussi

        }

    }

}


public boolean addImageToBuffer(int index){

    //Ajout de imageFile[index] à la fin du buffer

    //Retourne vrai si l'ajout a réussi

    PixelImage pixel_img = null;

    Image img = null;

    pixel_img = ToolkitLoader.loadViaToolkitOrCodecs(imageFile[index].toString());

    if(pixel_img==null){

        return false;

    }

    img = (Image) ImageCreator.convertToAwtImage(pixel_img,ImageCreator.DEFAULT_ALPHA);

    tracker.addImage(img,0);

    try {

        tracker.waitForID(0);

    } catch (InterruptedException e) {

        return false;

    }

    boolean bool = buffer.add(img);

    bufferSize++;

    pixel_img = null;

    return bool;

}

Si vous avez une idée ? Merci pour votre aide.

6 réponses

Messages postés
5367
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
27 janvier 2022
111
Salut,

Utilise wait et notify en tre tes deux thread pour les synchroniser
 déjà en fesant cela tu va limiter les problèmes

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

WORA
Messages postés
4
Date d'inscription
vendredi 11 août 2006
Statut
Membre
Dernière intervention
17 août 2006

Merci Twinuts


J'ai essayé ton idée en ajoutant des wait() et notify() dans ces fonctions.

J'obtient sensiblement le même résultat qu'en mettant synchronized pour
ces même méthodes: toute la séquence s'affiche mais la vitesse de
rafraichissement est vraiment trop lente... :(
Messages postés
5367
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
27 janvier 2022
111
Salut,

essaye ça pour voir :

public synchronized void run() {
    System.out.println("Début Afficheur");
    Image image=null;
    if(buffer==null){
        System.out.println("Buffer d'image non initialisé !");
        return;
    }
    while(makingVideo){
       try{
        wait();
       }catch(Exception e){
       }
        image = buffer.getNextImage();
        if((image==null)&&(!bufferRunner.isAlive())){
            //Fin de la vidéo
            makingVideo = false;
            return;
        }
        canva.set_image(image);//L'image est transmise au canva puis déssinée
        for(int i=0;i<nbParam;i++){
            ((MyGraphicPanel)panelVector.elementAt(i)).goToNextPoint();
        }
    }
    buffer.killThread();//Arret du remplissage
    System.out.println("Fin Afficheur");
}

public synchronized wakeUp(){
    notify();
}

et dans le thread de remplissage tu fais appel à la methode wakeup une foir que le boulot est fait apres si tu as toujour des ralentissement cela peut venir du mediatraker qui prend trop de temps donc essai si tu peux de le remplacer par
new ImageIcon(im).getImage() ce qui peut prendre moins de temps bien que je n'en soit pas à 100% certain

exemple:
....
img = (Image) ImageCreator.convertToAwtImage(pixel_img,ImageCreator.DEFAULT_ALPHA);
boolean bool = buffer.add(new ImageIcon(img).getImage());
bufferSize++;
pixel_img = null;

threadRemplissage.wakeUp();
return bool;
....

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

WORA
Messages postés
4
Date d'inscription
vendredi 11 août 2006
Statut
Membre
Dernière intervention
17 août 2006

Salut.

J'avais utilisé notify() et wait de cette façon :

public synchronized Image getNextImage(){

        if(bufferSize<=0){

            try {

                this.wait();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        Image img =(Image)buffer.removeFirst();

        tracker.removeImage(img);//On retire l'image du MediaTracker

        bufferSize--;

        this.notify();

        return (img);

    }


    public synchronized boolean addImageToBuffer(int index){

        //Ajout de imageFile[index] à la fin du buffer

        //Retourne vrai si l'ajout a réussi

        PixelImage pixel_img = null;

        Image img = null;

        if(bufferSize>=maxSize){

            //Buffer plein

            try {

                this.wait();

            } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

        pixel_img = ToolkitLoader.loadViaToolkitOrCodecs(imageFile[index].toString());

        if(pixel_img==null){

            return false;

        }

        img = (Image) ImageCreator.convertToAwtImage(pixel_img,ImageCreator.DEFAULT_ALPHA);

        tracker.addImage(img,0);

        try {

                    tracker.waitForID(0);

            } catch (InterruptedException e) {

                    return false;

            }

        boolean bool = buffer.add(img);

        bufferSize++;

        pixel_img = null;

        this.notify();

        return bool;

    }


... de cette façon, l'objet ou les threads sont mis en attente est le
buffer puisque ces 2 fonctions sont appellées dans ce dernier.

    getNextImage() est appellée par le thread qui affiche

    addImageToBuffer(int index) est appellée par le thread qui rempli le buffer

Cette solution est équivalente à la précédente je pense, c'est juste
que l'objet sur lesquels sont fait les notify() et les wait() sont
différents.


Finalement j'ai toujours les ralentissements (et l'exécution des thread
semble resté séquencielle: un remplissage, un affichage...).

Je ne peux pas utiliser ImageIcon(im).getImage() car le format
des images n'est pas pris en charge par Java (des images au format TIFF
sont possibles). Le problème ne semble pas venir de la librairie que
j'ai utilisé car j'ai testé avec des images PNG (donc sans utilisé la
librairie pour les images TIFF) et j'obtient le même résultat.

Le problème dois venir du MediaTracker. N'y a t-il pas moyen de le rendre plus rapide ? ou quelqu'un a t-il une autre solution ?

Merci de votre aide.
Messages postés
5367
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
27 janvier 2022
111
Salut,

tu as essayé de ne pas utiliser le mediatracker?

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

WORA
Messages postés
4
Date d'inscription
vendredi 11 août 2006
Statut
Membre
Dernière intervention
17 août 2006

Re,


Je viens d'essayer et il n'y a pas de changements visibles (je n'ai pas
vérifié les temps d'exécution, j'ai juste regarder la séquence). Il
faut croire qu'il est inutile ici, peut etre que le chargement de
l'image se fait lors de l'appelle de la fonction ToolkitLoader.loadViaToolkitOrCodecs( ).

En fait, je pense que le problème dois venir de l'enchainement des
threads puisque lorsque le remplissage est fini, arrêt du thread de
remplissage, le buffer contient N images et leur affichage se fait
correctement (la fréquence de rafraichissement s'accélère). Sinon en
tant normal, l'exécution des threads semble être séquentiel, en mettant
des prinln() on obtient :

    Affichage

    Remplissage

    Affichage

    Remplissage

    ...