简体   繁体   English

在JPanel内部旋转BufferedImage

[英]Rotate BufferedImage Inside JPanel

I am trying to rotate a BufferedImage and display it inside a JLabel (which is inside a JPanel ). 我正在尝试旋转BufferedImage并将其显示在JLabel (位于JPanel )内。 The current result produces a white square rotated 10 degrees against a black background, but the image is not present inside the square. 当前结果产生一个白色正方形,相对于黑色背景旋转了10度,但正方形内部不存在图像。 I know myPicture is not blank, since myPicture itself displays properly inside the JPanel when not rotated. 我知道myPicture不是空白的,因为不旋转时myPicture本身可以正确显示在JPanel内部。

Here is the code: 这是代码:

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

There's not a lot to go on, but two things come to mind. 没有太多的事情要做,但是有两件事要想到。 It's possible that the image is not been rendered in the correct position after it's been rotated and two, you're not disposing of the Graphics context when you're done with it (not that I believe it should have an effect, but you never know). 旋转后,图像可能未正确显示在正确的位置;第二,处理完Graphics ,您不会处理Graphics上下文(不是我认为它应该有效果,但是您永远不会知道)。

This is a simple example that renders the result via paintComponent , but the concept is the same. 这是一个通过paintComponent渲染结果的简单示例,但是概念是相同的。

It uses an AffineTransformation to rotate the image. 它使用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();

        }
    }
}

Update using a JLabel 使用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());

        }
    }
}

I solved my own issue. 我解决了自己的问题。 The problem lay in the code: 问题在于代码:

myPicture.getType()

Since there is a lot of variability in the types of images you could put in to the program, the results are going to be unpredictable when you start drawing into the new BufferedImage. 由于可以放入程序中的图像类型存在很多可变性,因此当您开始绘制到新的BufferedImage中时,结果将是不可预测的。 I solved the problem by setting the type explicitly, which in my case required 我通过显式设置类型来解决问题,在我的情况下需要

BufferedImage.TYPE_INT_ARGB

so the full statement read: 因此,完整的语句为:

BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM