java swing rotation jpanel bufferedimage

java - Girar BufferedImage Inside JPanel



swing rotation (2)

No hay mucho para seguir, pero dos cosas vienen a la mente. Es posible que la imagen no se haya renderizado en la posición correcta después de haberla girado y dos, no se deshace del contexto de Graphics cuando haya terminado con ella (no es que crea que deba tener un efecto, pero nunca saber).

Este es un ejemplo simple que representa el resultado a través de paintComponent , pero el concepto es el mismo.

Utiliza una AffineTransformation para rotar la imagen.

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

Actualizar usando un 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()); } } }

Estoy tratando de rotar una BufferedImage y mostrarla dentro de un JLabel (que está dentro de un JPanel ). El resultado actual produce un cuadrado blanco girado 10 grados sobre un fondo negro, pero la imagen no está presente dentro del cuadrado. Sé que myPicture no está en blanco, ya que myPicture se muestra correctamente dentro del JPanel cuando no se gira.

Aquí está el código:

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


Resolví mi propio problema. El problema radica en el código:

myPicture.getType()

Dado que hay una gran variabilidad en los tipos de imágenes que puede poner en el programa, los resultados serán impredecibles cuando comience a dibujar en la nueva Imagen Buffered. Resolví el problema estableciendo el tipo explícitamente, que en mi caso requería

BufferedImage.TYPE_INT_ARGB

entonces la declaración completa decía:

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