1

我正在尝试旋转 aBufferedImage并将其显示在 a 内JLabel(在 a 内JPanel)。当前结果会生成一个在黑色背景上旋转 10 度的白色正方形,但正方形内不存在图像。我知道myPicture不是空白,因为myPicture它本身JPanel在未旋转时正确显示。

这是代码:

int w = myPicture.getWidth();    

int h = myPicture.getHeight();  

BufferedImage newImage = new BufferedImage(w, h, myPicture.getType());

Graphics2D graphic = newImage.createGraphics();

graphic.rotate(Math.toRadians(10), w/2, h/2);

graphic.drawImage(myPicture, null, 0, 0);

picLabel.setIcon(new ImageIcon(newImage));
4

2 回答 2

8

没有太多事情要做,但有两件事浮现在脑海中。图像在旋转后可能没有被渲染到正确的位置,两个,Graphics当你完成它时你没有处理上下文(不是我相信它应该有效果,但你永远不知道)。

这是一个通过 渲染结果的简单示例paintComponent,但概念是相同的。

它使用一个AffineTransformation来旋转图像。

在此处输入图像描述

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.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TestRotateImage {

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

    public TestRotateImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JSlider slider;
        private BufferedImage image;

        public TestPane() {
            setLayout(new BorderLayout());

            try {
                image = ImageIO.read(new File("/path/to/your/image"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            slider = new JSlider();
            slider.setMinimum(0);
            slider.setMaximum(360);
            slider.setMinorTickSpacing(5);
            slider.setMajorTickSpacing(10);
            slider.setValue(0);
            add(slider, BorderLayout.SOUTH);
            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    repaint();
                }
            });
        }

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

        public double getAngle() {

            return Math.toRadians(slider.getValue());

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setColor(Color.RED);
            g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
            g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);

            g2d.setColor(Color.BLACK);
            int x = (getWidth() - image.getWidth()) / 2;
            int y = (getHeight() - image.getHeight()) / 2;
            AffineTransform at = new AffineTransform();
            at.setToRotation(getAngle(), x + (image.getWidth() / 2), y + (image.getHeight() / 2));
            at.translate(x, y);
            g2d.setTransform(at);
            g2d.drawImage(image, 0, 0, this);
            g2d.dispose();

        }
    }
}

使用 JLabel 更新

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
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.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TestRotateImage {

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

    public TestRotateImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JSlider slider;
        private BufferedImage image;
        private JLabel label;

        public TestPane() {
            setLayout(new BorderLayout());

            label = new JLabel();
            label.setHorizontalAlignment(JLabel.CENTER);
            label.setVerticalAlignment(JLabel.CENTER);

            try {
                image = ImageIO.read(new File("/path/to/your/image"));
                label.setIcon(new ImageIcon(image));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            add(label);

            slider = new JSlider();
            slider.setMinimum(0);
            slider.setMaximum(360);
            slider.setMinorTickSpacing(5);
            slider.setMajorTickSpacing(10);
            slider.setValue(0);
            add(slider, BorderLayout.SOUTH);
            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    double radians = Math.toRadians(slider.getValue());
                    double sin = Math.abs(Math.sin(radians));
                    double cos = Math.abs(Math.cos(radians));
                    int newWidth = (int)Math.round(image.getWidth() * cos + image.getHeight() * sin);
                    int newHeight = (int)Math.round(image.getWidth() * sin + image.getHeight() * cos);

                    BufferedImage rotate = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g2d = rotate.createGraphics();
                    int x = (newWidth - image.getWidth()) / 2;
                    int y = (newHeight - image.getHeight()) / 2;
                    AffineTransform at = new AffineTransform();
                    at.setToRotation(getAngle(), x + (image.getWidth() / 2), y + (image.getHeight() / 2));
                    at.translate(x, y);
                    g2d.setTransform(at);
                    g2d.drawImage(image, 0, 0, TestPane.this);
                    g2d.dispose();
                    label.setIcon(new ImageIcon(rotate));
                }
            });
        }

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

        public double getAngle() {

            return Math.toRadians(slider.getValue());

        }
    }
}
于 2013-04-03T06:12:04.943 回答
0

我解决了我自己的问题。问题在于代码:

myPicture.getType()

由于您可以放入程序的图像类型存在很大差异,因此当您开始绘制新的 BufferedImage 时,结果将是不可预测的。我通过明确设置类型解决了这个问题,在我的情况下需要

BufferedImage.TYPE_INT_ARGB

所以完整的声明如下:

BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
于 2013-04-03T16:31:24.337 回答