[英]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.