Christophe Jacquet, Associate Professor at Supélec

Enseignement > Exemples en Java >

Dessin dans une image en mémoire

Lorsqu'on veut dessiner à l'écran, on recommande généralement de placer le code de dessin dans la méthode paintComponent() d'un composant Swing. Or, si le dessin est très complexe, cela peut être pénalisant, en particulier si le dessin en question peut être effectué une fois pour toutes.

Cet exemple explique donc comment il est possible d'effectuer une fois pour toutes le dessin dans un tampon en mémoire, qui peut ensuite être utilisé par une méthode paintComponent() pour réactualiser les affichages. De plus, une image ainsi créée peut être très facilement enregistrée dans un fichier JPEG, PNG ou GIF.

/* ############################################################################
 * 
 * DessinEnMemoire.java : dessin dans des images stockées dans des tampons,
 *                        qui peuvent être enregistrés sous forme d'images
 *                        ou affichés dans des fenêtres Swing.
 *                        Lorsqu'un programme doit réaliser des dessins
 *                        complexes, cela permet par exemple de les effectuer
 *                        une fois pour toutes dans un tampon, et évite de
 *                        devoir les refaire à chaque appel de paintComponent()
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2006-11-27  Création
 * 2011-05-15  Changement de nom
 * 
 * ############################################################################
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ImagesEtTampons {
	public static void main(String[] args) {
		/*
		 * 1 - Création et initialisation d'un tampon image
		 */
		
		// crée le tampon pour l'image
		final BufferedImage image = 
			new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
		
		// récupère un objet Graphics pour pouvoir dessiner sur l'image
		// nous récupérons en fait un objet Graphics2D, qui offre bien plus
		// de fonctionnalités qu'un simple objet Graphics
		Graphics2D g = (Graphics2D)image.getGraphics();
		
		// active le lissage des formes
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
	             RenderingHints.VALUE_ANTIALIAS_ON);

		
		/*
		 * 2 - Dessin dans l'image
		 */
		
		// dessine des formes
		g.setColor(Color.RED);
		g.fillRect(10, 10, 200, 100);
		
		g.setColor(Color.GREEN);
		g.fillOval(100, 100, 60, 80);
		
		g.setFont(new Font("sans-serif", Font.ITALIC, 20));
		g.setColor(Color.YELLOW);
		g.drawString("Test de BufferedImage.", 150, 250);
		
		
		/*
		 * 3 - Écriture de l'image dans un fichier
		 */
		try {
			// types possibles : jpeg, png, gif
			ImageIO.write(image, "png", new File("test.png"));
		} catch(IOException e) {
			System.err.println("Erreur lors de l'écriture de l'image.");
		}
		
		
		/*
		 * 4 - Affichage de l'image à l'écran dans une fenêtre Swing
		 */
		SwingUtilities.invokeLater(new Runnable() {
		    public void run() {
		    	creerEtAfficherFenetre(image);
		    }
		});
		// cette construction permet d'appeler la méthode creerEtAfficherFenetre
		// depuis le thread de diffusion d'événements de Swing. L'appeler
		// depuis le thread principal de l'application peut mener à des
		// problèmes de concurrence difficiles à dépanner.
	}
	
	/**
	 * Crée et affichage à l'écran une fenêtre contenant une image donnée.
	 * 
	 * @param image l'image à afficher.
	 */
	@SuppressWarnings("serial")
	private static void creerEtAfficherFenetre(final BufferedImage image) {
		JFrame fenetre = new JFrame("Affichage d'image");
		
		fenetre.add(new JPanel() {
			/** 
			 * surcharge de paintComponent de façon à afficher le
			 * contenu de notre BufferedImage.
			 */
			@Override
			public void paintComponent(Graphics g) {
				g.drawImage(image, 0, 0, null);
			}
			
			/** Constructeur qui définit la taille préférée du panneau */
			{
				setPreferredSize(
						new Dimension(image.getWidth(), image.getHeight()));
			}
		}, BorderLayout.CENTER);
		
		fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		fenetre.pack();
		
		fenetre.setVisible(true);
	}
}