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

2D Java Discussion :

Rotation et flip d'une image


Sujet :

2D Java

  1. #1
    Membre actif Avatar de aDamas
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 260
    Points : 288
    Points
    288
    Par défaut Rotation et flip d'une image
    Bonjour, j'aimerais pouvoir réaliser des rotations de +/-90° et des effet mirroir (flip) sur une image, le problème c'est que après une rotation le flip se fait dans le mauvais sens un flip vertical devient horizontal...

    je procède ainsi :

    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
    17
     
    /*placement des axes au centre de l'image*/
    g2D.translate(decalageX,decalageY);
    g2D.scale(-1,1);
    g2D.rotate(Math.PI);  
     
    /*mise à l'endroit de l'image*/ 	
    g2D.scale(1,-1);
     
    /*rotation et symétrie*/   	
    g2D.rotate(flipHorizontal*flipVectical*Math.toRadians(angle));
    g2D.scale(flipHorizontal,flipVectical); //1 ou -1
     
    /* dessin de l'image */ 	
    g2D.drawImage(imageToDraw, centreToX,centreToY, null);
     
    // operation inverse pour remplacer le systeme d'axe comme avant
    J'ai voulu corriger en disant que si l'image avait déjà subit une rotation alors les flips s'inversent, mais à ce moment là, c'est la rotation de l'image qui se fait à l'envers après un flip.

    Je m'arrache les cheveux la dessus depuis un moment alors si quelqu'un pouvait m'aider, mon cuir chevelu apprecierait.
    Merci

  2. #2
    Membre émérite
    Avatar de xavlours
    Inscrit en
    Février 2004
    Messages
    1 832
    Détails du profil
    Informations forums :
    Inscription : Février 2004
    Messages : 1 832
    Points : 2 410
    Points
    2 410
    Par défaut
    Bonjour, as tu essayé d'inverser les opérations scale et rotate ?
    "Le bon ni le mauvais ne me feraient de peine si si si je savais que j'en aurais l'étrenne." B.V.
    Non au langage SMS ! Je ne répondrai pas aux questions techniques par MP.
    Eclipse : News, FAQ, Cours, Livres, Blogs.Et moi.

  3. #3
    Membre actif Avatar de aDamas
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 260
    Points : 288
    Points
    288
    Par défaut
    Affrimatif! mais après c'est l'inverse, c'est à dire qu'après un flip, c'est la rotation qui se fait à l'envers...

  4. #4
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Ce qui est normal puisque le repere a change et est maintenant oriente dans l'autre sens a savoir vers le haut (en supposant une inversion de l'axe Y si flip == mirroir/symetrie suivant l'axe des X).
    Essaie de faire une rotation avec l'angle oppose (-theta).

    Sauf erreur de ma part pour un mirroir (symetrie suivant l'axe des Y) il faudrait faire PI-theta .... a calculer egalement la transformation appropriee de la rotation lors un combo des 2 symetries axiales (= une symetrie centrale)...

    Essaie egalement de voir si tu ne peux pas utiliser la classe AffineTransform et composer (la methode concatenate() ... l'ordre de concatenation est important) les operations entre elles au lieu de te prendre la tete avec les primitives de Graphics.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  5. #5
    Membre du Club Avatar de lebesnec
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 82
    Points : 63
    Points
    63
    Par défaut
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    	/**
             * tourne l'image sur la gauche
             */
    	public void rotateRight(java.awt.Image img) {
    	    BufferedImage newImg2= new BufferedImage(getHeight(), getWidth(), BufferedImage.TYPE_INT_RGB);
    	    BufferedImage newImg = toBufferedImage(getImage());
     
    	    AffineTransform tx = new AffineTransform();
    	    AffineTransform tx2 = new AffineTransform();
    	    tx.rotate((Math.toRadians(90)),(getWidth()/2),((getHeight())/2));
    	    tx.translate((getWidth()-getHeight())/2,(getWidth()-getHeight())/2);
    	    AffineTransformOp op = new AffineTransformOp(tx,  AffineTransformOp.TYPE_BILINEAR);
    	    AffineTransformOp op2 = new AffineTransformOp(tx2,  AffineTransformOp.TYPE_BILINEAR);
     
    	    op.filter(newImg,newImg2) ;
    	    op2.filter(newImg2,null) ;
    	    save(newImg2);
    	}
     
    	/**
             * tourne l'image sur la droite
             */
    	public void rotateLeft() {
    		BufferedImage newImg2= new BufferedImage(getHeight(), getWidth(), BufferedImage.TYPE_INT_RGB);
    		BufferedImage newImg = toBufferedImage(getImage());
     
    			AffineTransform tx = new AffineTransform();
    			AffineTransform tx2 = new AffineTransform();
    			tx.rotate((Math.toRadians(270)),(getWidth()/2),((getHeight())/2));
    			tx.translate((getHeight()-getWidth())/2,(getHeight()-getWidth())/2);
    			 AffineTransformOp op = new AffineTransformOp(tx,  AffineTransformOp.TYPE_BILINEAR);
    			 AffineTransformOp op2 = new AffineTransformOp(tx2,  AffineTransformOp.TYPE_BILINEAR);
     
    			 op.filter(newImg,newImg2) ;
    			 op2.filter(newImg2,null) ;
    			 save(newImg2);
    	}
     
        /**
         * @param image     l'image à convertir
         * @return l'image convertit en BufferedImage
         */
        public static BufferedImage toBufferedImage(java.awt.Image image) {
            // On test si l'image n'est pas déja une instance de BufferedImage
            if (image instanceof BufferedImage) {
                // cool, rien à faire
                return ((BufferedImage) image);
            } else {
                // On s'assure que l'image est complètement chargée
                image = new ImageIcon(image).getImage();
     
                // On crée la nouvelle image
                BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null),
                        BufferedImage.TYPE_INT_RGB);
                Graphics g = bufferedImage.createGraphics();
                g.drawImage(image, 0, 0, null);
                g.dispose();
     
                return (bufferedImage);
            }
        }
    si ça peut te rassurer il nous a fallue 4 jours à 3 personnes pour pondre ça
    et ça doit certainement pas être la méthode la plus propre
    Chercher dans la Javadoc directement depuis Firefox / IE7 : http://lebesnec.free.fr/?p=8

  6. #6
    Membre actif Avatar de aDamas
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 260
    Points : 288
    Points
    288
    Par défaut
    Mais là tu fais qu'une rotation non? Mon problème c'est pas la rotation de l'image, mais le cumul d'une rotation et d'un effet de mirroir...

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Chaque transformation s'effectue dans le repère courant transformé par la transformation précédement appliquée et non pas dans le repère d'origine. Donc si tu veux faire "une rotation de 90° + une symétrie par rapport à X" la symétrie s'effectue dans le repère transformé par la rotation à savoir ca devient une symétrie par rapport à l'axe Y (au sens repère de l'écran).... ainsi de suite...

    Soit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Shape rectangle = new Rectangle(0, 0, 100, 50);
    AffineTransform rotation = AffineTransforme.getRotateInstance(Math.PI/2.0);
    AffineTransform scale = AffineTransforme.getScaleInstance(-1, 1);
    Ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    shape = rotation.createTransformedShape(shape);
    shape = scale.createTransformedShape(shape);
    Ne donne pas la même chose (sauf erreur de ma part) que cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    AffineTransforme transform = (AffineTransform)rotation.clone();
    transform.concatenate(scale);
    shape = transform.createTransformedShape(shape);
    Ce dernier code etant l'équivalent de ce que tu fais à savoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    graphics.rotate(Math.PI/2.0);
    graphics.scale(-1, 1);
    graphics.drawRect(0, 0, 100, 50);
    Il existe un moyen simple de t'en rendre compte :

    - imprime ton image sur une feuille de papier;
    - dessine un repère orthonormé en son centre (orienté comme sur l'écran à savoir avec l'axe Y orienté vers le bas).
    - fait une rotation de 90° à la feuille (dans le sens des aiguilles d'une montre dans ce repère donc).
    - maintenant fait une symétrie par rapport à l'axe X du repère dessiné sur la feuille
    Maintenant tu as la même transformation de ton image que ce que tu obtiens à l'écran.

    donc tu remarqueras que si tu veux faire une symétrie par rapport à ton axe X comme tu le voulais initialement : il faut en fait faire une symétrie par rapport à l'axe Y de la feuille
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Membre actif Avatar de aDamas
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    260
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2004
    Messages : 260
    Points : 288
    Points
    288
    Par défaut
    Le problème c'est qu'il me semble que je fais ça correctement... Mon code complet est le suivant :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    Image imageToDraw=image.getImage();
    double decalageX=(imageToDraw.getWidth(null)*zoom/2);
    double decalageY=(imageToDraw.getHeight(null)*zoom/2);
    int centreToX=-(imageToDraw.getWidth(null)/2);
    int centreToY=-(imageToDraw.getHeight(null)/2);
    int ceflipHorizontal=	flipHorizontal;// 1 ou -1
    int ceflipVectical=flipVectical;// 1 ou -1
     
     
        	if(this.rotation==90||this.rotation==-270||this.rotation==-90||this.rotation==270)
        		{
        		ceflipVectical=	flipHorizontal;
        		ceflipHorizontal=flipVectical;
        		decalageX=(imageToDraw.getHeight(null)*zoom/2);
        		decalageY=(imageToDraw.getWidth(null)*zoom/2);
        		centreToX=-(imageToDraw.getHeight(null)/2);
        		centreToY=-(imageToDraw.getWidth(null)/2);
        		}
     
    g2D.translate(decalageX,decalageY);
    g2D.scale(-1,1);
    g2D.rotate(Math.PI);    	
    g2D.scale(1,-1);  
     
    g2D.scale(zoom,zoom);
     
    g2D.rotate(flipHorizontal*flipVectical*Math.toRadians(this.rotation));
     
    g2D.scale(ceflipHorizontal,ceflipVectical);
    g2D.drawImage(imageToDraw, centreToX,centreToY, null);
    g2D.scale(ceflipHorizontal,ceflipVectical);
        	g2D.rotate(-(flipHorizontal*flipVectical*Math.toRadians(this.rotation)));
     
    g2D.scale(1/zoom,1/zoom);
     
    g2D.scale(1,-1);
    g2D.rotate(-Math.PI);
    g2D.scale(-1,1);
    g2D.translate(-decalageX,-decalageY);

    Y a vraiment de quoi péter un plomb...

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Plop.

    J'avais besoin de faire une simple rotation sur une image, je me suis servi du code fourni par lebesnec (merci beaucoup au passage) pour régler le problème de translation qui apparait après une rotation.

    Une idée de la raison de ce "décalage"? Pourquoi devoir faire une translation alors qu'on a fourni à la rotation le bon centre de l'image? Est-ce lié au problème de changement de repère évoqué par bouye?

  10. #10
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Le fait qu'il y ait un decallage est on ne peut plus normal compte tenu des changements de repere :

    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
     
    package test;
     
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.LinearGradientPaint;
    import java.awt.RenderingHints;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Rectangle2D;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
     
    /**
     */
    public class TestTransform extends JPanel {
     
        public enum Transform {
     
            NONE, ROTATE, ROTATE_FLIP;
     
            public AffineTransform getTranform(float cx, float cy) {
                AffineTransform result = null;
                switch (this) {
                    case ROTATE_FLIP:
                        result = AffineTransform.getRotateInstance(Math.PI / 2.0, cx, cy);
                        result.concatenate(AffineTransform.getScaleInstance(1, -1));
                        break;
                    case ROTATE:
                        result = AffineTransform.getRotateInstance(Math.PI / 2.0, cx, cy);
                        break;
                    case NONE:
                    default:
                        result = new AffineTransform();
                }
                return result;
            }
        }
        private Transform transform = Transform.NONE;
        private float width = 150;
        private float height = 100;
        private Rectangle2D.Float rect = new Rectangle2D.Float(0, 0, width, height);
        private float cx = width / 2f;
        private float cy = height / 2f;
        private float radius = 5;
        private Ellipse2D.Float center = new Ellipse2D.Float(cx - radius, cy - radius, 2 * radius, 2 * radius);
        private LinearGradientPaint paint = new LinearGradientPaint(0, 0, width, height, new float[]{0, 0.5f, 1}, new Color[]{Color.ORANGE, Color.BLUE, Color.GREEN});
     
        public TestTransform(Transform t) {
            if (t != null) {
                transform = t;
            }
            setPreferredSize(new Dimension(400, 350));
        }
     
        /**
         * {@inheritDoc}
         */
        @Override
        protected void paintComponent(Graphics graphics) {
            super.paintComponent(graphics);
            Dimension size = getSize();
            Graphics2D g2d = (Graphics2D) graphics.create();
            try {
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                ///////////////////////
                g2d.translate(100, 100);
                g2d.setColor(Color.MAGENTA);
                g2d.drawLine(0, 0, 100, 0);
                g2d.drawLine(0, 0, 0, 100);
                /////////////////////////////////////////////////
                AffineTransform t = transform.getTranform(cx, cy);
                g2d.transform(t);
                g2d.setPaint(paint);
                g2d.fill(rect);
                g2d.setPaint(Color.BLACK);
                g2d.draw(rect);
                g2d.setPaint(Color.GREEN);
                g2d.fill(center);
                g2d.setPaint(Color.ORANGE);
                g2d.draw(center);
                g2d.setColor(Color.RED);
                g2d.drawLine(0, 0, 100, 0);
                g2d.drawLine(0, 0, 0, 100);
                g2d.drawString("X", 100, -20);
                g2d.drawString("Y", -20, 100);
     
            } finally {
                g2d.dispose();
            }
            graphics.setColor(Color.BLACK);
            graphics.drawRect(0, 0, size.width - 1, size.height - 1);
            //
            graphics.setXORMode(Color.WHITE);
            graphics.drawString(transform.toString(), 50, 50);
            graphics.setPaintMode();
        }
     
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            // TODO code application logic here
            SwingUtilities.invokeLater(new Runnable() {
     
                public void run() {
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
                    frame.add(new TestTransform(Transform.NONE));
                    frame.add(new TestTransform(Transform.ROTATE));
                    frame.add(new TestTransform(Transform.ROTATE_FLIP));
                    frame.pack();
                    frame.setVisible(true);
                }
            });
        }
    }

    Nom : flipflop.jpg
Affichages : 1196
Taille : 31,7 Ko Nom : g4178-8-5.png
Affichages : 1233
Taille : 20,8 Ko
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  11. #11
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Bonjour,

    j'ai eu besoin de réaliser une rotation d'image et ayant bénéficié de vos commentaires sur ce post, je vous propose de voir le code (simple) que j'ai réalisé et qui répond je pense aux questions posées

    Voir le code : http://serge.coude.net/code-source/java.php5

    Serge

Discussions similaires

  1. Rotation d'une image 2D
    Par FidoDido® dans le forum Traitement d'images
    Réponses: 12
    Dernier message: 29/06/2011, 11h55
  2. Correction de rotation(en Z) dans une image 2D
    Par syn_42 dans le forum Développement 2D, 3D et Jeux
    Réponses: 3
    Dernier message: 05/04/2006, 15h58
  3. rotation d'une image
    Par KHEOPS1982 dans le forum Composants VCL
    Réponses: 2
    Dernier message: 17/12/2005, 17h21
  4. Rotation d'une image TIFF
    Par Tub-95 dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 14/10/2005, 20h56
  5. Définir un angle de rotation pour une image
    Par mateo.14 dans le forum C++
    Réponses: 5
    Dernier message: 25/03/2005, 14h43

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