2013-11-28 17 views
6

Tôi đã có lớp được gọi là Airplane. Bên trong lớp này tôi đã có biến img là một loại BufferedImage.Xoay ảnh bằng AffineTransform

@Override 
public void paintComponent(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.drawImage(mapa, 0, 0, getWidth(), getHeight(), null); 
    drawAirplanes(g2d); 
} 

Chức năng drawAirplanes() cái nhìn như thế này::

private void drawAirplane(Graphics2D g){ 
    for(Samolot i: s){ 
     i.rotateAirplane(); 
     g.drawImage(i.getImg(),i.getX(),i.getY(),(int)i.getDim().getWidth(),(int)i.getDim().getHeight(), null); 
    } 
} 

Nó đơn giản chỉ cần 1) xoay máy bay (BufferedImage bên trong đối tượng trên máy bay) 2) vẽ tôi hơn tôi đã có lớp WorldMap mà đè chức năng paintComponent(Graphics g) là gì anh ta.

Airplane.rotateAirplane của tôi() chức năng trông như thế này:

public void rotateSamolot() { 
    AffineTransform tx = new AffineTransform(); 

    tx.translate(10,10); //10, 10 is height and width of img divide by 2 
    tx.rotate(Math.PI/2); 
    tx.translate(-10,-10); 

    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); 

    BufferedImage newImage =new BufferedImage(20, 20, img.getType()); //20, 20 is a height and width of img ofc 
    op.filter(img, newImage); 

     this.img = newImage; 
} 

OFC khi im chạy chương trình của tôi chỉ mapa đối tượng được rút ra. khi im xóa làn này

this.img = newImage;

tôi đã nhận OFC máy bay của tôi quá nhưng không xoay.

+0

Tôi không chắc chắn bạn muốn dịch các AffineTransform, bạn nên, thay vào đó, cung cấp các điểm quay với phương pháp xoay, mà thường là điểm trung tâm, nhưng đó là vào bạn. Tôi cũng sẽ không chỉ định kết quả của việc quay trở lại hình ảnh chính nếu không bạn tăng lãi kép .... – MadProgrammer

+1

Tôi "nghĩ" về cơ bản những gì đang xảy ra, là hình ảnh của bạn đang được quay "ngoài giới hạn" của không gian có sẵn ... – MadProgrammer

+1

Bạn có thể xem [ví dụ này] (http://stackoverflow.com/questions/15779877/rotate-bufferedimage-inside-jpanel/15780090#15780090) – MadProgrammer

Trả lời

12

Vấn đề chính (mà tôi có thể nhìn thấy) là bản dịch của ngữ cảnh Graphics được bù đắp vị trí xoay vòng sẽ diễn ra.

Tôi "nghĩ" xoay theo mặc định xảy ra ở góc trên cùng/bên trái của ngữ cảnh Graphics (vị trí của nó là 0x0 mà bạn đã dịch sang thứ khác), điều này có thể khiến hình ảnh bị xoay vòng khung (hoặc khu vực có thể xem)

Bạn nên cung cấp điểm "neo" nơi xoay vòng diễn ra, thông thường, trung tâm là sở thích cá nhân của tôi.

Ví dụ sau chỉ đơn giản là có hình ảnh chính (do các ràng buộc về kích thước tôi phải mở rộng nó, nhưng bạn có thể không cần điều này). Sau đó tôi sử dụng điều này để tạo ra một thể hiện "xoay" có kích thước để cho phép hình ảnh phù hợp với bên trong. Điều này rất thú vị với trig - tôi lấy trộm mã từ đâu đó, vì vậy hãy ghi nhận cho nhà phát triển đó.

Ví dụ này cho phép bạn nhấp vào bất kỳ vị trí nào và nó sẽ thay đổi trục quay để bạn có thể xem điều gì đang diễn ra. Vị trí mặc định là trung tâm của cửa sổ ...

Spinning

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.AffineTransform; 
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.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SampleRotation { 

    public static void main(String[] args) { 
     new SampleRotation(); 
    } 

    public SampleRotation() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       final RotationPane rotationPane = new RotationPane(); 
       final JSlider slider = new JSlider(0, 100); 
       slider.addChangeListener(new ChangeListener() { 
        @Override 
        public void stateChanged(ChangeEvent e) { 
         double angle = 720d * (slider.getValue()/100d); 
         rotationPane.setAngle(angle); 
        } 
       }); 
       slider.setValue(0); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(rotationPane); 
       frame.add(slider, BorderLayout.SOUTH); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class RotationPane extends JPanel { 

     private BufferedImage img; 
     private BufferedImage rotated; 
     private double angle; 
     private Point clickPoint; 

     public RotationPane() { 
      try { 
       img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/issue459.jpg")); 
       BufferedImage scaled = new BufferedImage(img.getWidth()/2, img.getHeight()/2, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D g2d = scaled.createGraphics(); 
       g2d.setTransform(AffineTransform.getScaleInstance(0.5d, 0.5d)); 
       g2d.drawImage(img, 0, 0, this); 
       g2d.dispose(); 
       img = scaled; 
       setAngle(0d); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 

      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mouseClicked(MouseEvent e) { 
        clickPoint = e.getPoint(); 
        repaint(); 
       } 

      }); 

     } 

     public void setAngle(double angle) { 
      this.angle = angle; 

      double rads = Math.toRadians(getAngle()); 
      double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads)); 
      int w = img.getWidth(); 
      int h = img.getHeight(); 
      int newWidth = (int) Math.floor(w * cos + h * sin); 
      int newHeight = (int) Math.floor(h * cos + w * sin); 

      rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); 
      Graphics2D g2d = rotated.createGraphics(); 
      AffineTransform at = new AffineTransform(); 
      at.translate((newWidth - w)/2, (newHeight - h)/2); 

      int x = clickPoint == null ? w/2 : clickPoint.x; 
      int y = clickPoint == null ? h/2 : clickPoint.y; 

      at.rotate(Math.toRadians(getAngle()), x, y); 
      g2d.setTransform(at); 
      g2d.drawImage(img, 0, 0, this); 
      g2d.setColor(Color.RED); 
      g2d.drawRect(0, 0, newWidth - 1, newHeight - 1); 
      g2d.dispose(); 

      repaint(); 
     } 

     public double getAngle() { 
      return angle; 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this)); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (rotated != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 

       int x = (getWidth() - rotated.getWidth())/2; 
       int y = (getHeight() - rotated.getHeight())/2; 
       g2d.drawImage(rotated, x, y, this); 

       g2d.setColor(Color.RED); 

       x = clickPoint == null ? getWidth()/2 : clickPoint.x; 
       y = clickPoint == null ? getHeight()/ 2 : clickPoint.y; 

       x -= 5; 
       y -= 5; 

       g2d.drawOval(x, y, 10, 10); 
       g2d.dispose(); 
      } 
     }   
    }  
} 
0

Đây là những gì làm việc cho tôi (kinda sao chép từ đây và ở đó):

public BufferedImage rotateImag (BufferedImage imag, int n) { //n rotation in gradians 

     double rotationRequired = Math.toRadians (n); 
     double locationX = imag.getWidth()/2; 
     double locationY = imag.getHeight()/2; 
     AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY); 
     AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);   
     BufferedImage newImage =new BufferedImage(imag.getWidth(), imag.getHeight(), imag.getType()); //20, 20 is a height and width of imag ofc 
     op.filter(imag, newImage); 

      //this.img = newImage; 
     return(newImage); 
    }