为了账号安全,请及时绑定邮箱和手机立即绑定

在JPanel内部旋转BufferedImage

/ 猿问

在JPanel内部旋转BufferedImage

一只萌萌小番薯 2019-12-06 15:36:26

我正在尝试旋转a BufferedImage并将其显示在a JLabel(位于内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));


查看完整描述

2 回答

?
开满天机

没有太多的事情要做,但是有两件事要想到。旋转后,图像可能未正确显示在正确的位置;第二,处理完图像后,您并没有丢弃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());


        }

    }

}


查看完整回答
反对 回复 2019-12-06
?
幕布斯6054654

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


myPicture.getType()

由于可以放入程序中的图像类型存在很多可变性,因此当您开始绘制到新的BufferedImage中时,结果将是不可预测的。我通过显式设置类型来解决问题,在我的情况下需要


BufferedImage.TYPE_INT_ARGB

因此,完整的语句为:


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


查看完整回答
反对 回复 2019-12-06

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信