SlideShare une entreprise Scribd logo
1  sur  4
Télécharger pour lire hors ligne
Groupe Vision, CUI, Université de Genève
                                                                       http://cui.unige.ch/DI/cours/1811/
                                                                       2001-2005, Julien Kronegg




            Utilisation de Java pour du
            traitement d’image - bases
Ce document se propose de montrer comment fonctionne la partie graphique bitmap de la
machine virtuelle Java, en particulier pour le traitement d’images numériques. Il ne s’agit pas
là d’un cours complet mais plutôt d’un exposé de la matière nécessaire pour bien réussir les
TPs.

Les méthodes basées ici utilisent exclusivement les classes standards des packages java.awt
et java.awt.image. Ces classes ne soient pas conçues spécifiquement pour le traitement
d’image, elles sont relativement inefficaces au niveau du temps CPU utilisé. D’autres
librairies, par exemple JIGL proposent de meilleurs outils pour le traitement d’image mais ne
seront pas exposées dans ce document.

Note : il est conseillé de ne pas imprimer ce document parce qu’il sera complété au fur et à
mesure du déroulement du cours et des TPs (en plus, ça économise du papier).

1    Introduction
Une image est représentée en Java par un objet de la classe Image. Un tel objet contient des
données telles que la taille de l'image, les couleurs des pixels de l'image ou le modèle de
couleur utilisé.

D'autres classes Java sont associées aux images et servent à leur traitement :
   • ImageProducer;
   • ImageConsumer;
   • ImageObserver;

L’ImageProducer agit comme un producteur selon le modèle producteur-consommateur.
C’est lui qui effectue par exemple du chargement de l’image.

L’ImageConsumer agit comme un consommateur selon le modèle producteur-consomateur.
C’est lui qui effectue le stockage des informations dans l’Image.

L’ImageObserver est le dispositif qui permet de contrôler le déroulement du processus
producteur-consomateur qui se déroule de manière asynchrone, comme nous le verrons plus
tard.

2    Chargement d'une image depuis un fichier
Java permet de charger des fichiers GIF, JPEG ou PNG depuis une unité de stockage (disque
ou réseau). Le fichier est chargé par la classe Applet ou Toolkit de java.awt par les
méthodes getImage ou createImage. Par exemple :

    Toolkit tk = Toolkit.getDefaultToolkit();
    Image img = tk.getImage("images/test.jpeg");

Les images sont chargées en fonction de la demande. Les choses se déroulent de la manière
suivante :

                                               1
1. la méthode getImage (ou createImage) crée une instance d'Image avec son
   ImageProducer associé et se termine immédiatement (aucune vérification si l'image
   existe vraiment);
2. lorsque l'image est nécessaire (par exemple pour un traitement ou pour l'affichage),
   l'Image demande à l'ImageConsumer la représentation en pixels de l’image ;
3. l’ImageConsumer demande alors à l’ImageProducer de charger l'image depuis le fichier
   (le chemin du fichier est stocké par l’ImageProducer);
                           ImageProducer            ImageConsumer                 Image
           fichier

Cette manière de procéder permet à un programme Java de démarrer sans que le chargement
des images ralentisse l'exécution (ce qui est normal puisque les images ne sont pas chargées).
L'inconvénient majeur est que l'image n'étant pas chargée, il n'est pas possible de connaître sa
taille.

Lorsque l’image est vraiment nécessaire, elle est chargée par une thread séparée du
programme principal, ce qui permet de ne pas bloquer l’application (p.ex. si il y a beaucoup
d'images à charger depuis une connexion lente). Il s’agit là d’un chargement asynchrone qui
pose le problème de savoir quand l’image est effectivement chargée. Pour cela, chaque
méthode utilisant une image prend en paramètre un ImageObserver qui est averti lorsque
l’image est chargée (ou en partie chargée) via sa méthode imageUpdate. Toute classe qui
hérite de Component implémente ImageObserver. Le comportement est alors de réafficher
le composant lorsque l’image est chargée (méthode repaint).

Ce mode de chargement asynchrone des images explique que toutes les méthodes utilisant des
images demandent un ImageObserver en paramètre.

Il est possible de forcer le chargement des images pour éviter le chargement sur demande.
Pour cela, on utilise le MediaTracker qui permet d’attendre jusqu’à ce qu’une ou plusieurs
images appartenant à un Component soient chargées :

    MediaTracker mt = new MediaTracker(unComponent); // p.ex. this
    mt.addImage(img,0);
    try {
      mt.waitForID(0);
    } catch (InterruptedException e) {
    }

Une    autre   méthode
                     existe pour charger une image.                 Il   s'agit    de     la   classe
javax.swing.ImageIcon qui utilise le MediaTracker :

    Image img = (new javax.swing.ImageIcon("nom_du_fichier.ext")).getImage();

3     Affichage d’une image
L’affichage d’une image est une chose relativement simple à comprendre lorsque l’on sait
comment les images sont chargées.

Tout Component peut afficher une image au moyen d’un objet Graphics, donné en
paramètre de la méthode paint du composant. La méthode à utiliser est drawImage (x0 et y0
sont les coordonnées d'origine de l'image sur le Graphics) :


                                               2
public void paint(Graphics g) {
      g.drawImage(uneImage, x0, y0, unImageObserver);
    }

Afin de réafficher le composant une fois que l’image a été chargée, il est nécessaire de choisir
l’ImageObserver à fournir en paramètre, le plus simple étant de donner le Component lui-
même (this).

Bien que tout composant puisse afficher une image, il est conseillé pour commencer de
choisir une Applet ou une Frame.

4    Accès aux pixels d’une image (Image -> int[])
L’accès aux valeurs des pixels d’une image consiste est réalisé par un ImageConsumer
particulier : le PixelGrabber.

Les pixels de l’image sont extraits dans un tableau d’entiers à une dimension et contenant le
autant de cases que de pixels dans l’image (stockage par ligne) :

    int[] pixels = new int[width * height];

Note: un int[] est un objet (au sens de Java). Par conséquent, l’affectation "int[] a = b;" ne
copie pas le tableau b dans le tableau a (deep copy), mais effectue une copie de référence
(shallow copy) : les deux tableaux pointent donc sur les même données. Donc, lorsqu’on
modifie l’un, ça modifie l’autre puisqu’il s’agit du même tableau. Pour effectuer une deep
copy, utiliser System.arraycopy().

Chaque pixel est code sur un int de 32 bits dont la représentation est la suivante1 :

                        31............. 24 23 ............ 16 15 .............. 8 7 .................0
                            alpha                red               green                 blue

La valeur alpha indique le niveau de transparence du pixel (0=transparent, 255=opaque). Les
valeurs red, green et blue indiquent le niveau des couleurs de base (0=0% de couleur de base,
255=100% de couleur de base). Les pixels sont acquis de la manière suivante :

    PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
    try {
      pg.grabPixels();
    } catch (InterruptedException e) {
      System.err.println("interrupted waiting for pixels!");
    }

Il est possible d'utiliser les opération de manipulation de bits sur chaque pixel (<< = shift à
gauche, >> = shift à droite, & = and, | = or).

5    Création d’une image (int[] -> Image)
Java ne permet pas d'afficher directement une image sous forme de tableau d'entiers mais
uniquement les objets de la classe Image. Pour cela, il faut convertir le tableau d'entier en

1
 Dans le cours d’imagerie, cela correspond à la description du § I.3.4.4 avec N=24 et K=32. Dans Windows XP,
c’est en général aussi comme cela que les couleurs sont codées (Propriétés d’affichage/Paramètres/Qualité
couleur : optimale (32 bits) ).
                                                         3
Image puis afficher cette Image. La création d’une image se fait sur le même principe que le
chargement de l’image depuis le disque puisqu’il s’agit aussi de créer une image. La
différence est que la source de donnée est un int[] au lieu d’un fichier :


             int[]         ImageProducer          ImageConsumer              Image


L’ImageProducer à utiliser est java.awt.image.MemoryImageSource et l’ImageConsumer
est par exemple le Toolkit utilisé pour charger l’image précédemment. Le code est donc le
suivant (MemoryImageSource est dans java.awt.image) :

    Toolkit tk = Toolkit.getDefaultToolkit();
    Image img = tk.createImage(new MemoryImageSource(width,height,pixels,0,width));

Note: le MemoryImageSource n’a besoin d’être créé que lorsque la taille de l’image change,
pas lorsque le contenu des pixels change. C’est normal puisque pixels est un int[], donc un
objet, il est passé par référence et non par valeur lors de la création du MemoryImageSource.

6     Comment sauver une image au format JPEG ou PNG
Pour sauver une Image, vous devez la convertir en BufferedImage, puis la sauver avec
ImageIO. Pour simplifier, vous pouvez utiliser la méthode suivante :

    import   javax.imageio.*;
    import   java.io.*;
    import   javax.swing.*;
    import   java.awt.image.*;

    /**
    Enregistre l'image sur le disque. Le format est défini par
    l'extension du fichier. Un message d'erreur est affiché si
    le format est inconnu.
    @param image_name nom de fichier à écrire. Doit se terminer par .JPEG ou .PNG
    @param img l’image à sauvegarder
    */
    public void save(String image_name, Image img) {
      BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = bi.createGraphics();
      g.drawImage(img, 0, 0, width, height, null);
      String file_format = image_name.substring(image_name.lastIndexOf('.')+1);
      try {
        boolean success = ImageIO.write(bi, file_format, new File(image_name));
        if (!success) {
          JOptionPane.showMessageDialog(new JFrame(), "Ecriture impossible:"+file_format);
      } catch (Exception e) {
        e.printStackTrace();
      }//end try
    }//end save

7     Paint & Repaint
Deux méthodes importantes de Component sont paint(Graphics g) et repaint().
Elles sont utilisées pour réafficher le contenu d’un Component. La méthode repaint() efface le
Graphics du composant et demande ensuite à la machine virtuelle Java de réafficher le
composant via la méthode paint(Graphics g): il s’agit donc d’un comportement asynchrone.
Pour forcer le réaffichage immédiat, on peut utiliser comp.paint(comp.getGraphics()), qui
évite l’effacement du Graphics et le réaffiche sans délai. Cette technique n’est normalement
nécessaire que lorsque vous avez un algorithme très gourmand en temps de calcul et que la
machine virtuelle n’a plus le temps de faire le réaffichage.

                                              4

Contenu connexe

En vedette

Manual de mantenimiento preventivo del monitor
Manual de mantenimiento preventivo del monitorManual de mantenimiento preventivo del monitor
Manual de mantenimiento preventivo del monitorEsa Silv:3
 
Présentation ardi action drjscs et csjc juin 2010
Présentation ardi action drjscs et csjc juin 2010Présentation ardi action drjscs et csjc juin 2010
Présentation ardi action drjscs et csjc juin 2010ARDI
 
Diaporama - Réunion secteur F du 21 octobre 2010
Diaporama - Réunion secteur F du 21 octobre 2010Diaporama - Réunion secteur F du 21 octobre 2010
Diaporama - Réunion secteur F du 21 octobre 2010Guérande
 
Musee egyptien 70
Musee egyptien 70Musee egyptien 70
Musee egyptien 70filipj2000
 
Rapport d'activité 2012
Rapport d'activité 2012Rapport d'activité 2012
Rapport d'activité 2012ATD13
 
Les tramways de la schlucht1
Les tramways de la schlucht1Les tramways de la schlucht1
Les tramways de la schlucht1Amarinois
 
Des images de soi
Des images de soiDes images de soi
Des images de soiGeersAlexie
 
L'interprétation du catharisme (herve rousseau)
L'interprétation du catharisme (herve rousseau)L'interprétation du catharisme (herve rousseau)
L'interprétation du catharisme (herve rousseau)Gerry Benedict
 
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...fdebas
 
Présentation ehf 2011
Présentation ehf 2011Présentation ehf 2011
Présentation ehf 2011bernardsoulier
 

En vedette (20)

Manual de mantenimiento preventivo del monitor
Manual de mantenimiento preventivo del monitorManual de mantenimiento preventivo del monitor
Manual de mantenimiento preventivo del monitor
 
Présentation ardi action drjscs et csjc juin 2010
Présentation ardi action drjscs et csjc juin 2010Présentation ardi action drjscs et csjc juin 2010
Présentation ardi action drjscs et csjc juin 2010
 
Le français
Le françaisLe français
Le français
 
Diaporama - Réunion secteur F du 21 octobre 2010
Diaporama - Réunion secteur F du 21 octobre 2010Diaporama - Réunion secteur F du 21 octobre 2010
Diaporama - Réunion secteur F du 21 octobre 2010
 
Insémination intra-vaginale chez le chien
Insémination intra-vaginale chez le chienInsémination intra-vaginale chez le chien
Insémination intra-vaginale chez le chien
 
Musee egyptien 70
Musee egyptien 70Musee egyptien 70
Musee egyptien 70
 
Rapport d'activité 2012
Rapport d'activité 2012Rapport d'activité 2012
Rapport d'activité 2012
 
Les tramways de la schlucht1
Les tramways de la schlucht1Les tramways de la schlucht1
Les tramways de la schlucht1
 
Japon pp
Japon ppJapon pp
Japon pp
 
Legislation de la vente
Legislation de la venteLegislation de la vente
Legislation de la vente
 
Act 4 formatos
Act 4 formatos Act 4 formatos
Act 4 formatos
 
Des images de soi
Des images de soiDes images de soi
Des images de soi
 
L'interprétation du catharisme (herve rousseau)
L'interprétation du catharisme (herve rousseau)L'interprétation du catharisme (herve rousseau)
L'interprétation du catharisme (herve rousseau)
 
Pv nimegue mai2013
Pv nimegue mai2013Pv nimegue mai2013
Pv nimegue mai2013
 
Small group session 1&2
Small group session 1&2Small group session 1&2
Small group session 1&2
 
Priere
PrierePriere
Priere
 
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...
Vente maison, real estate, Provence, France, aix-en-provence, bastide, mas, m...
 
Cocina espanola
Cocina espanolaCocina espanola
Cocina espanola
 
Présentation ehf 2011
Présentation ehf 2011Présentation ehf 2011
Présentation ehf 2011
 
大堡礁
大堡礁大堡礁
大堡礁
 

Similaire à Java Graphisme

Exemple d'utilisation de la génération GWT
Exemple d'utilisation de la génération GWTExemple d'utilisation de la génération GWT
Exemple d'utilisation de la génération GWTFrédéric Menou
 
Programmation graphique avancée en java
Programmation graphique avancée en javaProgrammation graphique avancée en java
Programmation graphique avancée en javaEzéquiel Tsagué
 
[Tutoriel] Insérer une image dans une application IBM i avec SilverDev
[Tutoriel] Insérer une image dans une application IBM i avec SilverDev[Tutoriel] Insérer une image dans une application IBM i avec SilverDev
[Tutoriel] Insérer une image dans une application IBM i avec SilverDevSilverDev by Experia
 
Convolutional Neural Networks (CNNs)
Convolutional Neural Networks (CNNs)Convolutional Neural Networks (CNNs)
Convolutional Neural Networks (CNNs)Hajar Bouchriha
 
Implémentation de l’algorithme du Simplexe En Java
Implémentation de l’algorithme du Simplexe En JavaImplémentation de l’algorithme du Simplexe En Java
Implémentation de l’algorithme du Simplexe En JavaRached Krim
 
Tutoriel de traitement d'images CCD cométaire avec Iris
Tutoriel de traitement d'images CCD cométaire avec IrisTutoriel de traitement d'images CCD cométaire avec Iris
Tutoriel de traitement d'images CCD cométaire avec IrisDidier Walliang
 
Traitement d'image sous Matlab
Traitement d'image sous Matlab  Traitement d'image sous Matlab
Traitement d'image sous Matlab Hajer Dahech
 
Microsoft Composition, pierre angulaire de vos applications ?
Microsoft Composition, pierre angulaire de vos applications ?Microsoft Composition, pierre angulaire de vos applications ?
Microsoft Composition, pierre angulaire de vos applications ?Microsoft
 
Java- LT informatique
Java-  LT informatiqueJava-  LT informatique
Java- LT informatiqueHassanChaaban
 
TP1 Traitement d'images Génie Logiciel avec Matlab
TP1 Traitement d'images Génie Logiciel avec MatlabTP1 Traitement d'images Génie Logiciel avec Matlab
TP1 Traitement d'images Génie Logiciel avec MatlabMariem ZAOUALI
 
Support tutoriel : Créer votre jeu en HTML5
Support tutoriel : Créer votre jeu en HTML5Support tutoriel : Créer votre jeu en HTML5
Support tutoriel : Créer votre jeu en HTML5SmartnSkilled
 
Extraction des routes par deep learning: ArcGIS Pro 2.9
Extraction des routes par deep learning: ArcGIS Pro 2.9Extraction des routes par deep learning: ArcGIS Pro 2.9
Extraction des routes par deep learning: ArcGIS Pro 2.9YOUSSOUPHA MBODJI
 
Android Lab Test : Ecrire un texte sur le canevas (français)
Android Lab Test : Ecrire un texte sur le canevas (français)Android Lab Test : Ecrire un texte sur le canevas (français)
Android Lab Test : Ecrire un texte sur le canevas (français)Bruno Delb
 
Flutter and ML Kit For Firebase
Flutter and ML Kit For FirebaseFlutter and ML Kit For Firebase
Flutter and ML Kit For FirebaseHamidou Bah
 
Computer Vision - Classification automatique des races de chien à partir de p...
Computer Vision - Classification automatique des races de chien à partir de p...Computer Vision - Classification automatique des races de chien à partir de p...
Computer Vision - Classification automatique des races de chien à partir de p...FUMERY Michael
 

Similaire à Java Graphisme (20)

Exemple d'utilisation de la génération GWT
Exemple d'utilisation de la génération GWTExemple d'utilisation de la génération GWT
Exemple d'utilisation de la génération GWT
 
5
55
5
 
Programmation graphique avancée en java
Programmation graphique avancée en javaProgrammation graphique avancée en java
Programmation graphique avancée en java
 
[Tutoriel] Insérer une image dans une application IBM i avec SilverDev
[Tutoriel] Insérer une image dans une application IBM i avec SilverDev[Tutoriel] Insérer une image dans une application IBM i avec SilverDev
[Tutoriel] Insérer une image dans une application IBM i avec SilverDev
 
Convolutional Neural Networks (CNNs)
Convolutional Neural Networks (CNNs)Convolutional Neural Networks (CNNs)
Convolutional Neural Networks (CNNs)
 
Implémentation de l’algorithme du Simplexe En Java
Implémentation de l’algorithme du Simplexe En JavaImplémentation de l’algorithme du Simplexe En Java
Implémentation de l’algorithme du Simplexe En Java
 
Tutoriel de traitement d'images CCD cométaire avec Iris
Tutoriel de traitement d'images CCD cométaire avec IrisTutoriel de traitement d'images CCD cométaire avec Iris
Tutoriel de traitement d'images CCD cométaire avec Iris
 
Traitement d'image sous Matlab
Traitement d'image sous Matlab  Traitement d'image sous Matlab
Traitement d'image sous Matlab
 
Microsoft Composition, pierre angulaire de vos applications ?
Microsoft Composition, pierre angulaire de vos applications ?Microsoft Composition, pierre angulaire de vos applications ?
Microsoft Composition, pierre angulaire de vos applications ?
 
Java- LT informatique
Java-  LT informatiqueJava-  LT informatique
Java- LT informatique
 
TP1 Traitement d'images Génie Logiciel avec Matlab
TP1 Traitement d'images Génie Logiciel avec MatlabTP1 Traitement d'images Génie Logiciel avec Matlab
TP1 Traitement d'images Génie Logiciel avec Matlab
 
Support tutoriel : Créer votre jeu en HTML5
Support tutoriel : Créer votre jeu en HTML5Support tutoriel : Créer votre jeu en HTML5
Support tutoriel : Créer votre jeu en HTML5
 
Swing
SwingSwing
Swing
 
Extraction des routes par deep learning: ArcGIS Pro 2.9
Extraction des routes par deep learning: ArcGIS Pro 2.9Extraction des routes par deep learning: ArcGIS Pro 2.9
Extraction des routes par deep learning: ArcGIS Pro 2.9
 
Formation ps
Formation psFormation ps
Formation ps
 
Backbonejs presentation
Backbonejs presentationBackbonejs presentation
Backbonejs presentation
 
Outils front-end
Outils front-endOutils front-end
Outils front-end
 
Android Lab Test : Ecrire un texte sur le canevas (français)
Android Lab Test : Ecrire un texte sur le canevas (français)Android Lab Test : Ecrire un texte sur le canevas (français)
Android Lab Test : Ecrire un texte sur le canevas (français)
 
Flutter and ML Kit For Firebase
Flutter and ML Kit For FirebaseFlutter and ML Kit For Firebase
Flutter and ML Kit For Firebase
 
Computer Vision - Classification automatique des races de chien à partir de p...
Computer Vision - Classification automatique des races de chien à partir de p...Computer Vision - Classification automatique des races de chien à partir de p...
Computer Vision - Classification automatique des races de chien à partir de p...
 

Java Graphisme

  • 1. Groupe Vision, CUI, Université de Genève http://cui.unige.ch/DI/cours/1811/ 2001-2005, Julien Kronegg Utilisation de Java pour du traitement d’image - bases Ce document se propose de montrer comment fonctionne la partie graphique bitmap de la machine virtuelle Java, en particulier pour le traitement d’images numériques. Il ne s’agit pas là d’un cours complet mais plutôt d’un exposé de la matière nécessaire pour bien réussir les TPs. Les méthodes basées ici utilisent exclusivement les classes standards des packages java.awt et java.awt.image. Ces classes ne soient pas conçues spécifiquement pour le traitement d’image, elles sont relativement inefficaces au niveau du temps CPU utilisé. D’autres librairies, par exemple JIGL proposent de meilleurs outils pour le traitement d’image mais ne seront pas exposées dans ce document. Note : il est conseillé de ne pas imprimer ce document parce qu’il sera complété au fur et à mesure du déroulement du cours et des TPs (en plus, ça économise du papier). 1 Introduction Une image est représentée en Java par un objet de la classe Image. Un tel objet contient des données telles que la taille de l'image, les couleurs des pixels de l'image ou le modèle de couleur utilisé. D'autres classes Java sont associées aux images et servent à leur traitement : • ImageProducer; • ImageConsumer; • ImageObserver; L’ImageProducer agit comme un producteur selon le modèle producteur-consommateur. C’est lui qui effectue par exemple du chargement de l’image. L’ImageConsumer agit comme un consommateur selon le modèle producteur-consomateur. C’est lui qui effectue le stockage des informations dans l’Image. L’ImageObserver est le dispositif qui permet de contrôler le déroulement du processus producteur-consomateur qui se déroule de manière asynchrone, comme nous le verrons plus tard. 2 Chargement d'une image depuis un fichier Java permet de charger des fichiers GIF, JPEG ou PNG depuis une unité de stockage (disque ou réseau). Le fichier est chargé par la classe Applet ou Toolkit de java.awt par les méthodes getImage ou createImage. Par exemple : Toolkit tk = Toolkit.getDefaultToolkit(); Image img = tk.getImage("images/test.jpeg"); Les images sont chargées en fonction de la demande. Les choses se déroulent de la manière suivante : 1
  • 2. 1. la méthode getImage (ou createImage) crée une instance d'Image avec son ImageProducer associé et se termine immédiatement (aucune vérification si l'image existe vraiment); 2. lorsque l'image est nécessaire (par exemple pour un traitement ou pour l'affichage), l'Image demande à l'ImageConsumer la représentation en pixels de l’image ; 3. l’ImageConsumer demande alors à l’ImageProducer de charger l'image depuis le fichier (le chemin du fichier est stocké par l’ImageProducer); ImageProducer ImageConsumer Image fichier Cette manière de procéder permet à un programme Java de démarrer sans que le chargement des images ralentisse l'exécution (ce qui est normal puisque les images ne sont pas chargées). L'inconvénient majeur est que l'image n'étant pas chargée, il n'est pas possible de connaître sa taille. Lorsque l’image est vraiment nécessaire, elle est chargée par une thread séparée du programme principal, ce qui permet de ne pas bloquer l’application (p.ex. si il y a beaucoup d'images à charger depuis une connexion lente). Il s’agit là d’un chargement asynchrone qui pose le problème de savoir quand l’image est effectivement chargée. Pour cela, chaque méthode utilisant une image prend en paramètre un ImageObserver qui est averti lorsque l’image est chargée (ou en partie chargée) via sa méthode imageUpdate. Toute classe qui hérite de Component implémente ImageObserver. Le comportement est alors de réafficher le composant lorsque l’image est chargée (méthode repaint). Ce mode de chargement asynchrone des images explique que toutes les méthodes utilisant des images demandent un ImageObserver en paramètre. Il est possible de forcer le chargement des images pour éviter le chargement sur demande. Pour cela, on utilise le MediaTracker qui permet d’attendre jusqu’à ce qu’une ou plusieurs images appartenant à un Component soient chargées : MediaTracker mt = new MediaTracker(unComponent); // p.ex. this mt.addImage(img,0); try { mt.waitForID(0); } catch (InterruptedException e) { } Une autre méthode existe pour charger une image. Il s'agit de la classe javax.swing.ImageIcon qui utilise le MediaTracker : Image img = (new javax.swing.ImageIcon("nom_du_fichier.ext")).getImage(); 3 Affichage d’une image L’affichage d’une image est une chose relativement simple à comprendre lorsque l’on sait comment les images sont chargées. Tout Component peut afficher une image au moyen d’un objet Graphics, donné en paramètre de la méthode paint du composant. La méthode à utiliser est drawImage (x0 et y0 sont les coordonnées d'origine de l'image sur le Graphics) : 2
  • 3. public void paint(Graphics g) { g.drawImage(uneImage, x0, y0, unImageObserver); } Afin de réafficher le composant une fois que l’image a été chargée, il est nécessaire de choisir l’ImageObserver à fournir en paramètre, le plus simple étant de donner le Component lui- même (this). Bien que tout composant puisse afficher une image, il est conseillé pour commencer de choisir une Applet ou une Frame. 4 Accès aux pixels d’une image (Image -> int[]) L’accès aux valeurs des pixels d’une image consiste est réalisé par un ImageConsumer particulier : le PixelGrabber. Les pixels de l’image sont extraits dans un tableau d’entiers à une dimension et contenant le autant de cases que de pixels dans l’image (stockage par ligne) : int[] pixels = new int[width * height]; Note: un int[] est un objet (au sens de Java). Par conséquent, l’affectation "int[] a = b;" ne copie pas le tableau b dans le tableau a (deep copy), mais effectue une copie de référence (shallow copy) : les deux tableaux pointent donc sur les même données. Donc, lorsqu’on modifie l’un, ça modifie l’autre puisqu’il s’agit du même tableau. Pour effectuer une deep copy, utiliser System.arraycopy(). Chaque pixel est code sur un int de 32 bits dont la représentation est la suivante1 : 31............. 24 23 ............ 16 15 .............. 8 7 .................0 alpha red green blue La valeur alpha indique le niveau de transparence du pixel (0=transparent, 255=opaque). Les valeurs red, green et blue indiquent le niveau des couleurs de base (0=0% de couleur de base, 255=100% de couleur de base). Les pixels sont acquis de la manière suivante : PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, pixels, 0, width); try { pg.grabPixels(); } catch (InterruptedException e) { System.err.println("interrupted waiting for pixels!"); } Il est possible d'utiliser les opération de manipulation de bits sur chaque pixel (<< = shift à gauche, >> = shift à droite, & = and, | = or). 5 Création d’une image (int[] -> Image) Java ne permet pas d'afficher directement une image sous forme de tableau d'entiers mais uniquement les objets de la classe Image. Pour cela, il faut convertir le tableau d'entier en 1 Dans le cours d’imagerie, cela correspond à la description du § I.3.4.4 avec N=24 et K=32. Dans Windows XP, c’est en général aussi comme cela que les couleurs sont codées (Propriétés d’affichage/Paramètres/Qualité couleur : optimale (32 bits) ). 3
  • 4. Image puis afficher cette Image. La création d’une image se fait sur le même principe que le chargement de l’image depuis le disque puisqu’il s’agit aussi de créer une image. La différence est que la source de donnée est un int[] au lieu d’un fichier : int[] ImageProducer ImageConsumer Image L’ImageProducer à utiliser est java.awt.image.MemoryImageSource et l’ImageConsumer est par exemple le Toolkit utilisé pour charger l’image précédemment. Le code est donc le suivant (MemoryImageSource est dans java.awt.image) : Toolkit tk = Toolkit.getDefaultToolkit(); Image img = tk.createImage(new MemoryImageSource(width,height,pixels,0,width)); Note: le MemoryImageSource n’a besoin d’être créé que lorsque la taille de l’image change, pas lorsque le contenu des pixels change. C’est normal puisque pixels est un int[], donc un objet, il est passé par référence et non par valeur lors de la création du MemoryImageSource. 6 Comment sauver une image au format JPEG ou PNG Pour sauver une Image, vous devez la convertir en BufferedImage, puis la sauver avec ImageIO. Pour simplifier, vous pouvez utiliser la méthode suivante : import javax.imageio.*; import java.io.*; import javax.swing.*; import java.awt.image.*; /** Enregistre l'image sur le disque. Le format est défini par l'extension du fichier. Un message d'erreur est affiché si le format est inconnu. @param image_name nom de fichier à écrire. Doit se terminer par .JPEG ou .PNG @param img l’image à sauvegarder */ public void save(String image_name, Image img) { BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); g.drawImage(img, 0, 0, width, height, null); String file_format = image_name.substring(image_name.lastIndexOf('.')+1); try { boolean success = ImageIO.write(bi, file_format, new File(image_name)); if (!success) { JOptionPane.showMessageDialog(new JFrame(), "Ecriture impossible:"+file_format); } catch (Exception e) { e.printStackTrace(); }//end try }//end save 7 Paint & Repaint Deux méthodes importantes de Component sont paint(Graphics g) et repaint(). Elles sont utilisées pour réafficher le contenu d’un Component. La méthode repaint() efface le Graphics du composant et demande ensuite à la machine virtuelle Java de réafficher le composant via la méthode paint(Graphics g): il s’agit donc d’un comportement asynchrone. Pour forcer le réaffichage immédiat, on peut utiliser comp.paint(comp.getGraphics()), qui évite l’effacement du Graphics et le réaffiche sans délai. Cette technique n’est normalement nécessaire que lorsque vous avez un algorithme très gourmand en temps de calcul et que la machine virtuelle n’a plus le temps de faire le réaffichage. 4