Vous devez être membre et vous identifier pour publier un article.
Les visiteurs peuvent toutefois commenter chaque article par une réponse.
Swing - Comment faire pivoter une image en Swing?
Article publié le 31/01/2007 08:41:01Salut à toutes et à tous!
Aujourd'hui, une autre petite astuce qui va certainement plaireaux fanas de graphisme 2D....
Ne vous est-il jamais arrivé de devoir afficher une image sur un objet Graphics? Sûrement que oui.
Mais vous avez peut-être déjà éprouvé le besoin de devori faire pivoter cette image de x degrés à gauche ou à droite. Par exemple un vaisseau spatial dans un jeu d'arcade dont la direction du nez doit correspondre à la direction dans laquelle il se dirige.
La soultion est d'utiliser un objet AffineTransfrom, mais cela paraît parfois ardu. De plus, il peut être intéressant (toujours deans le cas du vaisseau de précalculer x images décalées de y degrés chacune de manière à disposer plus rapidement de l'image pivotée.
Dans ce but, j'ai écrit il y a quelques années une classe (RotatingImage) qui étend BufferedImage et qui peut donc être affichée sur un objet Graphics en uitlisant la méthode
Code Java (1 ligne)
drawImage()
L'emploi de cette classe est très simple. En voici le mode d'emploi:
1. Instanciez un objet BufferedImage:
Code Java (2 lignes)
URL imageURL = ...;
ou
Code Java (2 lignes)
2. Instanciez un objet RotatingImage:
Code Java (1 ligne)
rotatingImage = new RotatingImage(buffImage,true);
RotatingImage compte 3 constructeurs:
Le premier prend 3 arguments:
Code Java (1 ligne)
- sourceImage: la BufferedImage que vous venez d'instancier
- preCalc: une variable de type boolean qui spécifie si il faut précalculer les diférents images pivotées.
- numberOfImages: le nombre d'images a générer. Si par exemple cet argument vaut 10, alors 10 images pivotées de 36 degrés l'une par rapport à l'autre seront générées.
Le second prend 2 arguments:
Code Java (1 ligne)
En fait, il appelle le premier avec preCalc=false et numberOfImages=36
Le second n'en prend qu'un seul.
Code Java (1 ligne)
En fait, il appelle le second avec preCalc=false.
3. Spécifiez l'angle de rotation par rapport à l'image originale en utilisant la méthode
Code Java (1 ligne)
setAngle(double angle)
Code Java (1 ligne)
4. Afficher votre image sur un Graphics ou dans un label, par exemple:
- dans un Graphics:
Code Java (3 lignes)
gr.drawImage(rotatingImage, 100,100, null);
- dans un JLabel:
Remarques:
- Les images calculées sont stockées dans un objet Map. Les angles doivent être spécifiés en radians.
A chaque fois que vous utilisez la méthode
Code Java (1 ligne)
setAngle(double angle)
Par exemple, imaginons que vous ayez spécifié 30 images, elles seront alors espacées de 12 degrés chacune.
Si vous utilisez
Code Java (1 ligne)
C'est donc cette image qui sera affichée.
- N'utilisez cette classe qu'avec de images de petite taille ou en spécifiant un nombre d'iamges pas trop élévé, sans quoi vous obtindrez une Overflow exception... faites quelques tests.
Voici le code de la classe RotatingImage:
Code Java (201 lignes)
package be.fery.swing.rotatingImage; /** * This class enable image rotations. * * As it extends BufferedImage, it may be used * to be displayed on a Component or on a * Graphics object. * * @author Philippe FERY(philippe.fery@gmail.com) * @version 1.0 * * Created : November 2005 */ import java.awt.Graphics; import java.awt.Point; import java.awt.image.BufferedImage; import java.util.HashMap; private double angle; private int numberOfImages; private int sourceWidth; private int sourceHeight; private int rotatedWidth; private int rotatedHeight; super((int) Math.sqrt(sourceImage.getWidth() * sourceImage.getWidth() + sourceImage.getHeight() * sourceImage.getHeight()), (int) Math.sqrt(sourceImage.getWidth() * sourceImage.getWidth() + sourceImage.getHeight() * sourceImage.getHeight()), this.sourceImage = sourceImage; this.sourceWidth = sourceImage.getWidth(); this.sourceHeight = sourceImage.getHeight(); this.angle = 0; this.numberOfImages = numberOfImages; if (preCalc) preCalculateImages(); } this(sourceImage, preCalc, 36); } private void preCalculateImages() { for (int i = 0; i ‹ numberOfImages; i++) { rotate(); } long duration = end - begin; } this(sourceImage, false); } /** * Rotate the source image * */ public void rotate() { int rotatedWidth = (int) hypotenuseLength + 1; int rotatedHeight = (int) hypotenuseLength + 1; BufferedImage rotatedImage = new BufferedImage(rotatedWidth, rotatedHeight, BufferedImage.TYPE_INT_ARGB); int x = -1; int y = -1; } else { for (int xRot = 0; xRot ‹ rotatedWidth; xRot++) { for (int yRot = 0; yRot ‹ rotatedHeight; yRot++) { x = xyCoord.x; y = xyCoord.y; if (x ›= 0 && x ‹ sourceWidth && y ›= 0 && y ‹ sourceHeight) { int rgbColor = sourceImage.getRGB(x, y); try { rotatedImage.setRGB(xRot, yRot, rgbColor); } } } } } g.clearRect(0, 0, rotatedWidth, rotatedHeight); g.drawImage(rotatedImage, 0, 0, null); } /** * Get the corresponding coordinates in the source image for the specified * coordinates in the rotated image using the following transformation * matrix: | xSrc | = | xRot | | cos(angle) sin(angle) | | | | | * | | | * ySrc | = | yRot | | -sin(angle) cos(angle) | * * @param xRot * The x ccordinate in the rotated image * @param yRot * The y coordinate in the rotated image * * @return The corresponding (x,y) coordinate in the source image */ int dx = xRot; int dy = yRot; } /** * Get the corresponding coordinates in the rotated image for the specified * coordinates in the source image using the following transformation * matrix: | xSrc | = | xRot | | cos(angle) -sin(angle) | | | | | * | | | * ySrc | = | yRot | | sin(angle) cos(angle) | * * @param xRot * The x ccordinate in the source image * @param yRot * The y coordinate in the source image * * @return The corresponding (x,y) coordinate in the rotated image */ int dx = xSrc; int dy = ySrc; } /** * Get the angle value * * @return The rotation angle value */ public double getAngle() { return angle; } /** * Set the angle value * * @param angle * The rotation angle value */ public void setAngle(double angle) { this.angle = angle; rotate(); } /** * Get the source image * * @return The source image (not rotated) */ return sourceImage; } /** * Get the number of images * * @return The number of images to generate */ public int getNumberOfImage() { return numberOfImages; } /** * Set the number of images * * @param numberOfImages * The number of images to generate */ public void setNumberOfImage(int numberOfImages) { this.numberOfImages = numberOfImages; } }
Le code de cette classe peut évidemment être amélioré, mais je n'en ai pas le temps actuellement. Si le coeur vous en dit...
Voici quelques pistes:
- permettre de spécifier l'angle en degrés
- utiliser un objet AffineTransform pour effectuer les rotations plutôt que le calcule matriciel
- gérer la transparence
Vous êtes libres d'utilise ce code ou de transformer, mais en y laissant les commentaires en tête de classe.
Je vous demande juste de publier le code transformé ici même si vous l'avez amélioré. Ajoutez alors un tag
Code Java (1 ligne)
@author
HackTrack
Un article de HackTrackModifié 1 fois. (dernière modification le 31/01/2007 08:42:28 par HackTrack)
Source : indéterminée
Seuls les membres peuvent laisser un commentaire pour cet article (mesure automatique temporaire due aux attaques de spam par robots dont cet article fait actuellement l'objet).
31/01/2007 10:09:17 : Positionnement carto
Merci à toi pour cet article bien commenté.
Je vois déjà en quoi il peut m'être utile, car je vais bientôt développer un client riche pour une application carto. Je pense donc l'utiliser pour générer une sorte d'indicateur de direction vers le point de référence sur la carte.
Dès que j'ai quelque chôse, je vous en fait profiter.
- Akira Sato -
15/01/2010 15:51:25 : Convertir les radians en degrés
Bonjour,
Ta source est intéressante et j'aimerais vous faire profiter d'un ajout que l'on peut appliquer à celle-ci.
Pour passer des degrés en radians, il vous suffit de faire :
radian = degree * ((2 * Math.PI) / 360); // we translate degree to radian
Pour passer des radians en degrés, il vous suffit de faire :
degree = radian * (360 / (2 * Math.PI)); // we translate radian to degree
En espérant des développeurs(ses) en détresse ;)
Pierre-Yves (Pyrrah)
www.pyrrah.eu
- invité -
18/01/2010 21:08:17 : RE: Convertir les radians en degrés
Merci pour ces infos :-)
- Steph -
Commentaires
31/01/2007 10:09:17 : Positionnement carto
Merci à toi pour cet article bien commenté.
Je vois déjà en quoi il peut m'être utile, car je vais bientôt développer un client riche pour une application carto. Je pense donc l'utiliser pour générer une sorte d'indicateur de direction vers le point de référence sur la carte.
Dès que j'ai quelque chôse, je vous en fait profiter.
- Akira Sato -
15/01/2010 15:51:25 : Convertir les radians en degrés
Bonjour,
Ta source est intéressante et j'aimerais vous faire profiter d'un ajout que l'on peut appliquer à celle-ci.
Pour passer des degrés en radians, il vous suffit de faire :
radian = degree * ((2 * Math.PI) / 360); // we translate degree to radian
Pour passer des radians en degrés, il vous suffit de faire :
degree = radian * (360 / (2 * Math.PI)); // we translate radian to degree
En espérant des développeurs(ses) en détresse ;)
Pierre-Yves (Pyrrah)
www.pyrrah.eu
- invité -
18/01/2010 21:08:17 : RE: Convertir les radians en degrés
Merci pour ces infos :-)
- Steph -
Version en cache
22/12/2024 02:08:23 Cette version de la page est en cache (à la date du 22/12/2024 02:08:23) afin d'accélérer le traitement. Vous pouvez activer le mode utilisateur dans le menu en haut pour afficher la dernère version de la page.Document créé le 13/09/2004, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/ast-rf-382.html
L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.