Rotando una imagen a través de java.awt.geom.AffineTransform

30May08

Mediante AffineTransform se puede rotar una imagen dibujada sobre un Graphics.
Esto se debe a que en realidad AffineTransform agrega una transformada al objeto Graphipcs.

Para rotar se pasa a una instancia de AffineTransform a través de rotate(), pasándole el ángulo en radianes y el centro de rotación. Luego esta instancia se asigna al objeto Graphics (debemos asignársela a Graphics2D en realidad)

AffineTransform at = new AffineTransform();
at.rotate(r, 100, 100); //se asigna el angulo y centro de rotacion
((Graphics2D) g).setTransform(at);

Ejemplo

Por ejemplo creamos un panel que muestra un cuadrado girado una determinada cantidad de grados llamada JPanelImagenGiratoria.java:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;

public class JPanelImagenGiratoria extends javax.swing.JPanel {

    private int grados = 0;

    public int getGrados() {
        return grados;
    }

    public void setGrados(int grados) {
        this.grados = grados;
        repaint();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g); //se borra el contenido anterior

        double r = Math.toRadians(grados); //se convierte a radianes lo grados

        AffineTransform at = new AffineTransform();
        at.rotate(r, 100, 100); //se asigna el angulo y centro de rotacion
        ((Graphics2D) g).setTransform(at);

        //se dibuja
        g.setColor(Color.BLUE);
        g.drawRect(50, 50, 100, 100);

    }
}

y un frame para realizar la prueba del panel llamada PruebaPanel.java. Prestar atención al observador de cambios del JSlider agregado mediante addChangeListener():

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JSlider;

public class PruebaPanel{

    public static void main(String[] args) {
        final JFrame jf = new JFrame("Prueba Imagen Giratoria");
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setSize(200, 250);

        final JPanelImagenGiratoria ig = new JPanelImagenGiratoria();

        final JSlider js = new JSlider(0, 360);
        js.addChangeListener(new javax.swing.event.ChangeListener() {

            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                ig.setGrados(js.getValue());
            }
        });
        js.setValue(0);

        jf.setLayout(new BorderLayout());
        jf.add(ig, BorderLayout.CENTER);
        jf.add(js, BorderLayout.SOUTH);

        jf.setLocationRelativeTo(null);
        jf.setVisible(true);
    }
}

Imágenes:

Más Info



18 Responses to “Rotando una imagen a través de java.awt.geom.AffineTransform”

  1. 1 Santiago

    como podría mover el cubo en vez de con el ratón, que rotase con el dato que llega desde otro ordenador por UDP. el código del UDP lo tengo pero no se como meterlo en el Paint. en mi caso sería data1. tiene que ser fácil pero no lo veo y me tiene loco el tema…. te paso el código del UDP y te doy las gracias de antemano.

    //Receive reversed message from server
    inBuf = new byte[256];
    inPacket = new DatagramPacket(inBuf, inBuf.length);
    socket.receive(inPacket);

    String data = new String(inPacket.getData(), 0, inPacket.getLength());

    //int data1 =0
    //int grados=10;
    int data1 = Integer.parseInt(data);

  2. 2 coro4

    alguien me podria dar una pequeña ayuda con el clasico juego “Jackpot” para JFrame q´ corra 3 imagenes…se lo agradeceria

  3. 3 coro4

    gracias…parsero!!! fue de mucha ayda

  4. 4 yadi

    hola muxas gracias fue de muxa ayuda

  5. 5 edilasar

    que tal como estas soy principiente en sto y he tenido dificultad para realizar que me despliegue una imagen un programa me podrias ayudar gracias

  6. 6 alberto

    hola,
    he leido tu articulo soy nuevo en el tema de java y por lo tanto no se mucho de este lenguaje de programacion.
    }en la universidad me dejaron hacer un programa que dibuje unas coordenadas y que formen una figura all igual que tenga q rotar y escalar, mi duda es como agrego este codigo a el q tengo. por favor me podrias explicar, te repito soy nuevo en estos temas.
    package escalacion;

    /*
    * To change this template, choose Tools | Templates
    * and open the template in the editor.
    */

    /**
    *
    * @author Administrador
    */
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    import javax.swing.event.*;

    public class escalacion extends JApplet
    {
    JButton Calc=new JButton(“Agregar”);

    JButton reiniciar=new JButton(“Borrar”);
    JButton escala=new JButton(“Escalar”);
    JLabel C_x=new JLabel(“X=”);
    JLabel C_y=new JLabel(“Y=”);
    JLabel s_x=new JLabel(“X=”);
    JLabel s_y=new JLabel(“Y=”);
    JLabel Lim=new JLabel(“Escalacion”);
    JTextField V_cx=new JTextField(“”);
    JTextField V_cy=new JTextField(“”);
    JTextField s_cx=new JTextField(“”);
    JTextField s_cy=new JTextField(“”);

    Plano PC=new Plano(20);

    public void init()
    {
    this.setLayout(null);

    PC.setBounds(new Rectangle(180,0,500,500));
    C_x.setBounds(new Rectangle(10,10,40,15));
    C_y.setBounds(new Rectangle(10,30,40,15));
    V_cx.setBounds(new Rectangle(51,10,90,15));
    V_cy.setBounds(new Rectangle(51,30,90,15));
    Calc.setBounds(new Rectangle(10,50,130,20));

    reiniciar.setBounds(new Rectangle(10,70,130,20));

    Lim.setBounds(new Rectangle(40,100,120,20));

    s_cx.setBounds(new Rectangle(51,130,90,15));
    s_x.setBounds(new Rectangle(10,130,90,15));

    s_y.setBounds(new Rectangle(10,150,90,15));
    s_cy.setBounds(new Rectangle(51,150,90,15));
    escala.setBounds(new Rectangle(10,180,130,20));

    add(C_x);
    add(C_y);
    add(V_cx);
    add(V_cy);
    add(Calc);

    add(reiniciar);

    add(escala);
    add(Lim);
    add(s_cx);
    add(s_cy);
    add(s_x);
    add(s_y);

    // limites del plano
    PC.Limites(20, 20, -20, -20);
    PC.Origen();
    add(PC);
    this.setSize(700,500);

    //———-
    Calc.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e) {
    Calcular(e);
    }
    });

    reiniciar.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e) {
    V_cx.setText(“”);
    V_cy.setText(“”);
    PC.Reiniciar();
    }
    });

    escala.addActionListener(new ActionListener()
    {
    public void actionPerformed(ActionEvent e) {
    V_cx.setText(“”);
    V_cy.setText(“”);
    PC.finalizarTrazo();
    PC.traslacion(0);
    PC.escalar(Integer.parseInt(s_cx.getText()),Integer.parseInt(s_cy.getText()));

    }
    });
    }
    public void Calcular(ActionEvent e)
    {
    if(!isNumero(V_cx.getText()))
    {
    JOptionPane.showMessageDialog(this, “Inserta una cantidad válida para la coordenada X”);
    }
    else if(!isNumero(V_cy.getText()))
    {
    JOptionPane.showMessageDialog(this, “Inserta una cantidad válida para la coordenada X”);
    }
    else
    {
    PC.Punto(Double.parseDouble(V_cx.getText()),Double.parseDouble(V_cy.getText()));
    PC.repaint();
    }
    }
    public boolean isNumero(String Num)
    {
    boolean EsNum=false;
    String Nm=””;
    EsNum=isNaN(Num);
    if(EsNum)
    {
    return EsNum;
    }
    return EsNum;
    }
    /* si es un numero*/
    public boolean isNaN(String Num)
    {
    boolean yesNumber=false;
    double XNumber=0;
    try
    {
    XNumber=Double.parseDouble(Num);
    yesNumber=true;
    }
    catch(NumberFormatException e)
    {
    yesNumber=false;
    }
    return yesNumber;
    }

    }

    esta es la segunda clase
    import java.awt.*;

    public class Plano extends Canvas
    {
    public int inser =0, numser=0, n=0;
    public int[] x, y;
    public double MaxX, MaxY;
    public double maxx, maxy, minx, miny;
    public int posy[], posx[];
    public double etiqx[], etiqy[], cx[], cy[];
    public int numd, Xo, Yo;
    private int pos_ejex, pos_ejey;
    private int CoordenadasXH[][],CoordenadasYH[][];
    private int CoordenadasXV[][],CoordenadasYV[][];
    /**
    * Constructor de la clase:
    * @param cantidad: indica el numero de marcas que tendra el plano, es decir las etiquetas
    */
    public Plano(int cantidad)
    {
    this.setBackground(Color.white);
    numd=cantidad;
    MaxX=500;
    MaxY=500;
    etiqx = new double[numd];
    etiqy = new double[numd];
    posx = new int[numd];
    posy = new int[numd];
    inser=0;
    numser=500;
    }
    /**
    * Asigna los limites de los ejes, Xf, Xi, Yf, Yi
    * @param MaximoX
    * @param MaximoY
    * @param MinimoX
    * @param MinimoY
    */
    public void Limites(double MaximoX,double MaximoY,double MinimoX,double MinimoY)
    {
    minx=MinimoX;
    miny=MinimoY;
    maxx=MaximoX;
    maxy=MaximoY;
    this.EtiquetasX();
    this.EtiquetasY();
    this.LineasHorizontales();
    this.LineasVerticales();
    }
    public void LineasHorizontales()
    {
    int Cantidad=numd;
    CoordenadasXH=new int[Cantidad][2];
    CoordenadasYH=new int[Cantidad][2];
    for(int i=0; i<Cantidad; i++)
    {
    CoordenadasXH[i][0]=posx[i];
    CoordenadasXH[i][1]=0;
    CoordenadasYH[i][0]=posx[i];
    CoordenadasYH[i][1]=(int)MaxY;
    }
    }
    public void LineasVerticales()
    {
    int Cantidad=numd;
    CoordenadasXV=new int[Cantidad][2];
    CoordenadasYV=new int[Cantidad][2];
    for(int i=0; i= numser) return;

    y[inser] = (int) ((y0 – miny)/(maxy – miny)*(MaxY));
    cy[inser] = y0;

    inser++;
    }
    /**
    * Establce las coordenadas del origen en el plano
    */
    public void Origen()
    {
    Yo=(int) ((-miny)/(maxy – miny)*(MaxY));
    Xo=(int) ( (-minx)/(maxx – minx)*(MaxX));
    repaint();
    }
    /**
    * Las etiquetas de cada eje que conforman el plano aqui las del eje X
    * @param x0
    * @return
    */
    public void EtiquetasX()
    {
    double inc, aux;
    int i=0;
    if (inser==0)
    {
    x = new int[numser];
    cx = new double[numser];
    }
    inc = (maxx – minx) / numd;
    if (Math.abs(maxx – minx) > 1.0) {
    if (Math.abs(inc) < 1.0)
    inc = (double) 1.0;
    else
    inc = Math.round(inc + 0.5);
    }
    //inc = (maxx – minx) / numd;
    for (i = 0; i < numd; i++) {
    aux = minx + inc * i;
    aux = (Math.round(aux * 10000.0)) / 10000.0;
    etiqx[i] = aux;
    posx[i] = (int) ( (etiqx[i] – minx) / (maxx – minx) * (MaxX));
    }

    if (minx 0)
    pos_ejex = (int) ( -minx / (maxx – minx) * (MaxX));
    }
    /**
    * Las etiquetas de cada eje que conforman el plano aqui las del eje Y
    * @param x0
    * @return
    */
    public void EtiquetasY()
    {
    double inc, aux;
    int i=0;
    if(inser == 0)
    {
    y = new int[numser];
    cy = new double[numser];
    }

    inc = (maxy – miny)/numd;

    if( Math.abs(maxy – miny) > 1.0)
    {
    if(Math.abs(inc) < 1.0) inc = (double)1.0;
    else inc = Math.round(inc+0.5);
    }

    //inc = (maxy – miny)/numd;

    for(i=0; i<numd; i++)
    {
    aux = miny + inc*i;

    aux = (Math.round(aux*100000.0))/100000.0;
    etiqy[i] = aux;
    posy[i] = (int) ((etiqy[i] – miny)/(maxy – miny)*(MaxY));

    }
    if(miny 0)
    pos_ejey = (int)(MaxY -(int)(-miny /(maxy – miny)*(MaxY)));
    }
    public void Recalcular()
    {
    for(int i=0; i<inser; i++)
    {
    x[i]=(int) ( (cx[i] – minx) / (maxx – minx) * (MaxX));
    y[i]=(int) ( (cy[i] – miny) / (maxy – miny) * (MaxY));
    }
    repaint();
    }
    public void Restablecer()
    {
    pos_ejex=0;
    pos_ejey=0;
    }
    public void Reiniciar()
    {
    inser=0;
    repaint();
    }
    public void paint(Graphics g)
    {
    int i, j, mm;
    g.setColor(new Color(216,225,251));
    //Dibujar Lineas Verticales
    for(i=0; i<CoordenadasXH.length; i++)
    g.drawLine(CoordenadasXH[i][0], CoordenadasXH[i][1],CoordenadasYH[i][0], CoordenadasYH[i][1]);
    //Dibujar Lineas Horizontales
    for(i=0; i<CoordenadasXV.length; i++)
    g.drawLine(CoordenadasXV[i][0], (int)MaxY-CoordenadasXV[i][1],CoordenadasYV[i][0], (int)MaxY-CoordenadasYV[i][1]);

    // dibujar unas cuantas figuras
    g.setColor(Color.black);

    g.drawLine(pos_ejex, 0, pos_ejex, 500);
    g.drawLine(0, pos_ejey, 500, pos_ejey);
    for(i=0; i numser) mm = numser;
    else mm = inser;
    for(j=0; j<mm; j++)
    {
    g.setColor(new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255)));
    g.fillOval(x[j]-3, (int)MaxY-y[j]-3, 6, 6);
    g.drawString("A"+(j+1)+"("+cx[j]+","+cy[j]+")", x[j]-30, (int)MaxY-y[j]-10);
    }
    g.setColor(Color.black);
    g.drawOval(Xo-3, (int)MaxY-Yo-3, 6, 6);
    }
    public String Redondear(double val)
    {
    String aux="";
    double auxi=0;
    auxi=Math.round(val*100);
    aux=Integer.toString((int)(auxi/100));
    return aux;
    }
    }

    podrias decirme en que parte d este codigo agrego el de rotacion de figura

    • 7 tipo

      chabon pelotudo, hacete vos tu tarea, eso no es una pregunta…

  7. 8 Juan

    Gracias, en verdad que es de utilidad.

  8. that`s good

  9. @yarim si funciona exactamente igual, lo que cambia es lo que vos “dibujas” en el lienzo del panel.

    Después del comentario que dice “//se dibuja” del panel JPanelImagenGiratoria en vez de dibujar un cuadrado:

    g.drawRect(50, 50, 100, 100);
    

    dibujas la imagen :

    g.drawImage(imagen, 50, 50, 100, 100, this);
    

    Por supuesto que a la imagen la vá afectar el pixelado en mayor o menor medida

  10. 11 yarim

    hola, me pregunto si se puede rotar una imagen de la mis ma manera desde un archivo?

  11. @Mario revisá la parte en que le indicas que rote:

    at.rotate(r, ancho, alto); 
    

    si en verdad lo que queres hacer es:

    at.rotate(r, ancho/2, alto/2);
    

    colocando el centro de rotación en el centro del cuadrado

    Saludos

  12. 13 Mario

    Hola que tal, gracias por este tutorial me sirvió bastante para un trabajo que estoy haciendo de gráficos, tengo un pequeño problema, estoy haciendo un pequeño programa que dibuja un cuadrado, lo mueve de forma aleatoria, aumenta y disminuye de tamaño y además rota la imagen, pero me gustaría que rotara en la posición que queda… te mando la dirección si puedes checar a lo que me refiero y sugerir una solución … gracias por tu tiempo http://www.comboadictos.net/Mover_rotar.zip

  13. @Seba
    Estoy puliendo los últimos detalles para mi primer articulo para el JUG (espero que no sea el último)

    @Abraham
    Ahí te conteste

  14. Hola Le Funes,

    esto es completamente offtopic, pero no encontraba otra forma de contactar contigo. ¿Has recibido el correo que te he enviado tú cuenta de gmail?

  15. 16 Sebastian

    Felicitaciones, excelente post.

    Todavia espero un articulo tuyo en el JUG.

    Sebas

  16. me re sirvio!!!!
    muy buen articulo


  1. 1 Blog de JAVA - FinderIT » Blog Archive » Rotando una imagen a través de java.awt.geom.AffineTransform

A %d blogueros les gusta esto: