使用 AffineTransform 旋转图像 [英] Rotating Image with AffineTransform

查看:111
本文介绍了使用 AffineTransform 旋转图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 Airplane 的课程.在这个类中,我有一个变量 img,它是一个 BufferedImage 类型.更重要的是我有类 WorldMap 它覆盖了函数 paintComponent(Graphics g):

I have got class called Airplane. Inside this class i have got variable img which is a BufferedImage type. What is more i have got class WorldMap which overrides function paintComponent(Graphics g):

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

函数 drawAirplanes() 看起来像这样:

Function drawAirplanes() look like this:

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);
    }
}

它只需要1)旋转飞机(飞机对象内的BufferedImage)2)绘制他.​​

It simply need to 1) rotate airplane (BufferedImage inside Airplane object) 2) draw him.

我的 Airplane.rotateAirplane() 函数如下所示:

My Airplane.rotateAirplane() function looks like this:

 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 当我运行我的程序时,只绘制了 mapa 对象.当我删除这条车道时

ofc when im running my program only mapa object is drawn. when im deleting this lane

this.img = newImage;

我也有我的飞机,但没有旋转.

i have got ofc my airplane too but not rotated.

推荐答案

主要问题(我能看到的)是 Graphics 上下文的平移,它偏移了旋转将采取的位置地点.

The major problem (that I can see) is the translation of the Graphics context which is offset the position that the rotation will take place.

我认为"旋转默认发生在 Graphics 上下文的上/左角(它是 0x0 位置,您已将其转换为其他位置),这可能导致要旋转出框架(或可视区域)的图像

I "think" rotation by default occurs at the top/left corner of the Graphics context (where it's 0x0 position is, which you've translated to something else), this could be causing the image to be rotated out of frame (or viewable area)

您应该提供发生旋转的锚"点,通常,中心是我个人的喜好.

You should provide a "anchor" point where the rotation takes place, typically, the centre is my personal preference.

以下示例仅包含一个主图像(由于尺寸限制,我不得不对其进行缩放,但您可能不需要它).然后我使用它来生成一个旋转"实例,该实例的大小允许图像适合其中.trig 很有趣 - 我从某个地方窃取了代码,因此归功于该开发人员.

The following example simply has a master image (due to size constraints I had to scale it, but you may not need this). I then use this to generate a "rotated" instance which is sized to allow the image to fit within in. This is a lot of fun with trig - I stole the code from somewhere, so credit to that developer.

该示例允许您单击任意位置,它将更改旋转轴心,因此您可以看到发生了什么.默认位置是窗格的中心...

The example allows you to click any where and it will change the rotation pivot, so you can see what's going on. The default position is the centre of the pane...

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(rads, 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();
            }
        }        
    }    
}

这篇关于使用 AffineTransform 旋转图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆