Java 2D 旋转 BufferedImage

huangapple go评论83阅读模式
英文:

Java 2D rotate BufferedImage

问题

这个问题已经被回答了很多次,但我仍然不能将它应用到我的情况中。

我想将图像顺时针旋转90度。
我目前有以下代码:

  1. private void writeImage(BufferedImage sourceImage, String Path) throws IOException {
  2. BufferedImage result;
  3. Graphics2D g;
  4. AffineTransform at = new AffineTransform();
  5. // 在这里进行一些魔法操作,以正确旋转图像本身
  6. if (sourceImage.getWidth() > sourceImage.getHeight()) {
  7. // 进行一些在某种程度上奏效的操作:
  8. result = new BufferedImage(sourceImage.getHeight(null), sourceImage.getWidth(null), BufferedImage.TYPE_INT_RGB);
  9. g = result.createGraphics();
  10. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 抗锯齿!
  11. g.translate((result.getHeight() - result.getWidth()) / 2, (result.getHeight() - result.getWidth()) / 2);
  12. g.rotate(Math.toRadians(90f), sourceImage.getHeight() / 2, sourceImage.getWidth() / 2); // 尝试简单旋转
  13. } else {
  14. result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
  15. g = result.createGraphics();
  16. }
  17. //result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
  18. //g = result.createGraphics();
  19. /*
  20. if (result.getWidth() > result.getHeight()) {
  21. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 抗锯齿!
  22. //g.translate(170, 0);
  23. g.rotate(Math.toRadians(90));
  24. //g.translate((result.getHeight() - result.getWidth()) / 4, (result.getHeight() - result.getWidth()) / 4);
  25. //g.rotate(Math.PI / 2, result.getHeight() / 2, result.getWidth() / 2);
  26. //g.drawImage(sourceImage, 0, 0, result.getHeight(), result.getWidth(), Color.WHITE, null);
  27. //AffineTransformOp op = new AffineTransformOp(rotateClockwise90(result), AffineTransformOp.TYPE_BILINEAR);
  28. //op.filter(sourceImage, result);
  29. int tempHeight = result.getHeight();
  30. int tempWidth = result.getWidth();
  31. BufferedImage rotated = resize(result, tempHeight, tempWidth);
  32. //result = rotated;
  33. result = resize(result, result.getHeight(), result.getWidth());
  34. }*/
  35. g.drawImage(sourceImage, 0, 0, result.getWidth(), result.getHeight(), Color.WHITE, null);
  36. //g.drawImage(sourceImage, at, null);
  37. g.dispose();
  38. //BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
  39. //g = bufferedImage.createGraphics();
  40. //Color.WHITE estes the background to white. You can use any other color
  41. //g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);
  42. File output = new File(Path);
  43. OutputStream out = new FileOutputStream(output);
  44. ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
  45. ImageOutputStream ios = ImageIO.createImageOutputStream(out);
  46. writer.setOutput(ios);
  47. ImageWriteParam param = writer.getDefaultWriteParam();
  48. if (param.canWriteCompressed()) {
  49. param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
  50. param.setCompressionQuality(IMAGE_QUALITY);
  51. }
  52. writer.write(null, new IIOImage(result, null, null), param);
  53. out.close();
  54. ios.close();
  55. writer.dispose();
  56. }

当前结果

源图像和'BufferedImage sourceImage'如下所示:
源图像

我期望看到的是:
期望结果

谢谢!

英文:

This question was answered many time but I still can't apply it to my situation.

I want to rotate image on 90 degrees clockwise.
I'm currently having following code:

  1. private void writeImage(BufferedImage sourceImage, String Path) throws IOException {
  2. BufferedImage result;
  3. Graphics2D g;
  4. AffineTransform at = new AffineTransform();
  5. //Do some magic right here to correctly rotate the image itself
  6. if (sourceImage.getWidth() > sourceImage.getHeight()) {
  7. //Do some stuff that somehow works:
  8. result = new BufferedImage(sourceImage.getHeight(null), sourceImage.getWidth(null), BufferedImage.TYPE_INT_RGB);
  9. g = result.createGraphics();
  10. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti-alias!
  11. g.translate((result.getHeight() - result.getWidth()) / 2, (result.getHeight() - result.getWidth()) / 2);
  12. g.rotate(Math.toRadians(90f), sourceImage.getHeight() / 2, sourceImage.getWidth() / 2);//simple try
  13. } else {
  14. result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
  15. g = result.createGraphics();
  16. }
  17. //result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
  18. //g = result.createGraphics();
  19. /*
  20. if (result.getWidth() > result.getHeight()) {
  21. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti-alias!
  22. //g.translate(170, 0);
  23. g.rotate(Math.toRadians(90));
  24. //g.translate((result.getHeight() - result.getWidth()) / 4, (result.getHeight() - result.getWidth()) / 4);
  25. //g.rotate(Math.PI / 2, result.getHeight() / 2, result.getWidth() / 2);
  26. //g.drawImage(sourceImage, 0, 0, result.getHeight(), result.getWidth(), Color.WHITE, null);
  27. //AffineTransformOp op = new AffineTransformOp(rotateClockwise90(result), AffineTransformOp.TYPE_BILINEAR);
  28. //op.filter(sourceImage, result);
  29. int tempHeight = result.getHeight();
  30. int tempWidth = result.getWidth();
  31. BufferedImage rotated = resize(result, tempHeight, tempWidth);
  32. //result = rotated;
  33. result = resize(result, result.getHeight(), result.getWidth());
  34. }*/
  35. g.drawImage(sourceImage, 0, 0, result.getWidth(), result.getHeight(), Color.WHITE, null);
  36. //g.drawImage(sourceImage, at, null);
  37. g.dispose();
  38. //BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
  39. //g = bufferedImage.createGraphics();
  40. //Color.WHITE estes the background to white. You can use any other color
  41. //g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);
  42. File output = new File(Path);
  43. OutputStream out = new FileOutputStream(output);
  44. ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
  45. ImageOutputStream ios = ImageIO.createImageOutputStream(out);
  46. writer.setOutput(ios);
  47. ImageWriteParam param = writer.getDefaultWriteParam();
  48. if (param.canWriteCompressed()) {
  49. param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
  50. param.setCompressionQuality(IMAGE_QUALITY);
  51. }
  52. writer.write(null, new IIOImage(result, null, null), param);
  53. out.close();
  54. ios.close();
  55. writer.dispose();
  56. }

Current Result

The source image and 'BufferedImage sourceImage' looks like this:
Source Image

And what I expect to see is this:
Expected

Thanks!

答案1

得分: 1

这里是一个更通用的解决方案,允许旋转任意指定角度:

  1. import java.awt.*;
  2. import java.awt.geom.AffineTransform;
  3. import java.awt.image.BufferedImage;
  4. import java.io.IOException;
  5. import javax.imageio.ImageIO;
  6. import javax.swing.*;
  7. import javax.swing.event.*;
  8. import javax.swing.border.*;
  9. public class Rotation
  10. {
  11. public static BufferedImage rotateImage(BufferedImage original, double theta)
  12. {
  13. // 确定旋转后图像的大小
  14. double cos = Math.abs(Math.cos(theta));
  15. double sin = Math.abs(Math.sin(theta));
  16. double width = original.getWidth();
  17. double height = original.getHeight();
  18. int w = (int)(width * cos + height * sin);
  19. int h = (int)(width * sin + height * cos);
  20. // 创建空白图像并填充背景
  21. BufferedImage rotated = new BufferedImage(w, h, original.getType());
  22. Graphics2D g2 = rotated.createGraphics();
  23. g2.setPaint(UIManager.getColor("Panel.background"));
  24. g2.fillRect(0, 0, w, h);
  25. // 旋转图像
  26. double x = w/2;
  27. double y = h/2;
  28. AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
  29. x = (w - width)/2;
  30. y = (h - height)/2;
  31. at.translate(x, y);
  32. g2.drawRenderedImage(original, at);
  33. g2.dispose();
  34. return rotated;
  35. }
  36. private static void createAndShowGUI()
  37. {
  38. BufferedImage bi;
  39. try
  40. {
  41. String path = "mong.jpg";
  42. ClassLoader cl = Rotation.class.getClassLoader();
  43. bi = ImageIO.read( cl.getResourceAsStream(path) );
  44. }
  45. catch (Exception e) { return; }
  46. JLabel label = new JLabel( new ImageIcon( bi ) );
  47. label.setBorder( new LineBorder(Color.RED) );
  48. label.setHorizontalAlignment(JLabel.CENTER);
  49. JPanel wrapper = new JPanel();
  50. wrapper.add( label );
  51. JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
  52. slider.addChangeListener(new ChangeListener()
  53. {
  54. public void stateChanged(ChangeEvent e)
  55. {
  56. int value = slider.getValue();
  57. BufferedImage rotated = Rotation.rotateImage(bi, Math.toRadians(value) );
  58. label.setIcon( new ImageIcon(rotated) );
  59. }
  60. });
  61. JFrame frame = new JFrame("Rotation");
  62. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  63. frame.add(wrapper, BorderLayout.CENTER);
  64. frame.add(slider, BorderLayout.PAGE_END);
  65. frame.setSize(600, 600);
  66. frame.setLocationByPlatform( true );
  67. frame.setVisible( true );
  68. }
  69. public static void main(String[] args)
  70. {
  71. java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
  72. }
  73. }
英文:

Here is a more general solution that will allow rotation of any specified degrees:

  1. import java.awt.*;
  2. import java.awt.geom.AffineTransform;
  3. import java.awt.image.BufferedImage;
  4. import java.io.IOException;
  5. import javax.imageio.ImageIO;
  6. import javax.swing.*;
  7. import javax.swing.event.*;
  8. import javax.swing.border.*;
  9. public class Rotation
  10. {
  11. public static BufferedImage rotateImage(BufferedImage original, double theta)
  12. {
  13. // Determine the size of the rotated image
  14. double cos = Math.abs(Math.cos(theta));
  15. double sin = Math.abs(Math.sin(theta));
  16. double width = original.getWidth();
  17. double height = original.getHeight();
  18. int w = (int)(width * cos + height * sin);
  19. int h = (int)(width * sin + height * cos);
  20. // Create empty image and fill in background
  21. BufferedImage rotated = new BufferedImage(w, h, original.getType());
  22. Graphics2D g2 = rotated.createGraphics();
  23. g2.setPaint(UIManager.getColor("Panel.background"));
  24. g2.fillRect(0, 0, w, h);
  25. // Rotate the image
  26. double x = w/2;
  27. double y = h/2;
  28. AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
  29. x = (w - width)/2;
  30. y = (h - height)/2;
  31. at.translate(x, y);
  32. g2.drawRenderedImage(original, at);
  33. g2.dispose();
  34. return rotated;
  35. }
  36. private static void createAndShowGUI()
  37. {
  38. BufferedImage bi;
  39. try
  40. {
  41. String path = "mong.jpg";
  42. ClassLoader cl = Rotation.class.getClassLoader();
  43. bi = ImageIO.read( cl.getResourceAsStream(path) );
  44. }
  45. catch (Exception e) { return; }
  46. JLabel label = new JLabel( new ImageIcon( bi ) );
  47. label.setBorder( new LineBorder(Color.RED) );
  48. label.setHorizontalAlignment(JLabel.CENTER);
  49. JPanel wrapper = new JPanel();
  50. wrapper.add( label );
  51. JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
  52. slider.addChangeListener(new ChangeListener()
  53. {
  54. public void stateChanged(ChangeEvent e)
  55. {
  56. int value = slider.getValue();
  57. BufferedImage rotated = Rotation.rotateImage(bi, Math.toRadians(value) );
  58. label.setIcon( new ImageIcon(rotated) );
  59. }
  60. });
  61. JFrame frame = new JFrame("Rotation");
  62. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  63. frame.add(wrapper, BorderLayout.CENTER);
  64. frame.add(slider, BorderLayout.PAGE_END);
  65. frame.setSize(600, 600);
  66. frame.setLocationByPlatform( true );
  67. frame.setVisible( true );
  68. }
  69. public static void main(String[] args)
  70. {
  71. java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
  72. }
  73. }

答案2

得分: -1

尝试

  1. g.drawImage(sourceImage, 0, 0, sourceImage.getWidth(), sourceImage.getHeight(), Color.WHITE, null);
英文:

Try

  1. g.drawImage(sourceImage, 0, 0, sourceImage.getWidth(), sourceImage.getHeight(), Color.WHITE, null);

huangapple
  • 本文由 发表于 2020年9月26日 23:02:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/64079169.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定