Java 2D 旋转 BufferedImage

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

Java 2D rotate BufferedImage

问题

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

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

private void writeImage(BufferedImage sourceImage, String Path) throws IOException {

        BufferedImage result;
        Graphics2D g;
        AffineTransform at = new AffineTransform();

        // 在这里进行一些魔法操作,以正确旋转图像本身
        if (sourceImage.getWidth() > sourceImage.getHeight()) {

        // 进行一些在某种程度上奏效的操作:
            result = new BufferedImage(sourceImage.getHeight(null), sourceImage.getWidth(null), BufferedImage.TYPE_INT_RGB);
            g = result.createGraphics();

            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 抗锯齿!
            g.translate((result.getHeight() - result.getWidth()) / 2, (result.getHeight() - result.getWidth()) / 2);
            g.rotate(Math.toRadians(90f), sourceImage.getHeight() / 2, sourceImage.getWidth() / 2); // 尝试简单旋转

        } else {
            result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
            g = result.createGraphics();
        }

        //result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
        //g = result.createGraphics();

        /*
        if (result.getWidth() > result.getHeight()) {

            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 抗锯齿!
            //g.translate(170, 0);
            g.rotate(Math.toRadians(90));
            //g.translate((result.getHeight() - result.getWidth()) / 4, (result.getHeight() - result.getWidth()) / 4);
            //g.rotate(Math.PI / 2, result.getHeight() / 2, result.getWidth() / 2);
            //g.drawImage(sourceImage, 0, 0, result.getHeight(), result.getWidth(), Color.WHITE, null);
            //AffineTransformOp op = new AffineTransformOp(rotateClockwise90(result), AffineTransformOp.TYPE_BILINEAR);
            //op.filter(sourceImage, result);

            int tempHeight = result.getHeight();
            int tempWidth = result.getWidth();

            BufferedImage rotated = resize(result, tempHeight, tempWidth);

            //result = rotated;

            result = resize(result, result.getHeight(), result.getWidth());
        }*/

        g.drawImage(sourceImage, 0, 0, result.getWidth(), result.getHeight(), Color.WHITE, null);
        //g.drawImage(sourceImage, at, null);
        g.dispose();

        //BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
        //g = bufferedImage.createGraphics();
        //Color.WHITE estes the background to white. You can use any other color
        //g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);

        File output = new File(Path);
        OutputStream out = new FileOutputStream(output);

        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(out);
        writer.setOutput(ios);

        ImageWriteParam param = writer.getDefaultWriteParam();
        if (param.canWriteCompressed()) {
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(IMAGE_QUALITY);
        }

        writer.write(null, new IIOImage(result, null, null), param);

        out.close();
        ios.close();
        writer.dispose();
    }

当前结果

源图像和'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:

private void writeImage(BufferedImage sourceImage, String Path) throws IOException {
BufferedImage result;
Graphics2D g;
AffineTransform at = new AffineTransform();
//Do some magic right here to correctly rotate the image itself
if (sourceImage.getWidth() > sourceImage.getHeight()) {
//Do some stuff that somehow works:
result = new BufferedImage(sourceImage.getHeight(null), sourceImage.getWidth(null), BufferedImage.TYPE_INT_RGB);
g = result.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti-alias!
g.translate((result.getHeight() - result.getWidth()) / 2, (result.getHeight() - result.getWidth()) / 2);
g.rotate(Math.toRadians(90f), sourceImage.getHeight() / 2, sourceImage.getWidth() / 2);//simple try
} else {
result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
g = result.createGraphics();
}
//result = new BufferedImage(sourceImage.getWidth(null), sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
//g = result.createGraphics();
/*
if (result.getWidth() > result.getHeight()) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti-alias!
//g.translate(170, 0);
g.rotate(Math.toRadians(90));
//g.translate((result.getHeight() - result.getWidth()) / 4, (result.getHeight() - result.getWidth()) / 4);
//g.rotate(Math.PI / 2, result.getHeight() / 2, result.getWidth() / 2);
//g.drawImage(sourceImage, 0, 0, result.getHeight(), result.getWidth(), Color.WHITE, null);
//AffineTransformOp op = new AffineTransformOp(rotateClockwise90(result), AffineTransformOp.TYPE_BILINEAR);
//op.filter(sourceImage, result);
int tempHeight = result.getHeight();
int tempWidth = result.getWidth();
BufferedImage rotated = resize(result, tempHeight, tempWidth);
//result = rotated;
result = resize(result, result.getHeight(), result.getWidth());
}*/
g.drawImage(sourceImage, 0, 0, result.getWidth(), result.getHeight(), Color.WHITE, null);
//g.drawImage(sourceImage, at, null);
g.dispose();
//BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
//g = bufferedImage.createGraphics();
//Color.WHITE estes the background to white. You can use any other color
//g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);
File output = new File(Path);
OutputStream out = new FileOutputStream(output);
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(out);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(IMAGE_QUALITY);
}
writer.write(null, new IIOImage(result, null, null), param);
out.close();
ios.close();
writer.dispose();
}

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

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

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

public class Rotation
{
    public static BufferedImage rotateImage(BufferedImage original, double theta)
    {
        // 确定旋转后图像的大小

        double cos = Math.abs(Math.cos(theta));
        double sin = Math.abs(Math.sin(theta));
        double width  = original.getWidth();
        double height = original.getHeight();
        int w = (int)(width * cos + height * sin);
        int h = (int)(width * sin + height * cos);

        // 创建空白图像并填充背景

        BufferedImage rotated = new BufferedImage(w, h, original.getType());
        Graphics2D g2 = rotated.createGraphics();
        g2.setPaint(UIManager.getColor("Panel.background"));
        g2.fillRect(0, 0, w, h);

        // 旋转图像

        double x = w/2;
        double y = h/2;
        AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
        x = (w - width)/2;
        y = (h - height)/2;
        at.translate(x, y);
        g2.drawRenderedImage(original, at);
        g2.dispose();

        return rotated;
    }

    private static void createAndShowGUI()
    {
        BufferedImage bi;

        try
        {
            String path = "mong.jpg";
            ClassLoader cl = Rotation.class.getClassLoader();
            bi = ImageIO.read( cl.getResourceAsStream(path) );
        }
        catch (Exception e) { return; }

        JLabel label = new JLabel( new ImageIcon( bi ) );
        label.setBorder( new LineBorder(Color.RED) );
        label.setHorizontalAlignment(JLabel.CENTER);

        JPanel wrapper = new JPanel();
        wrapper.add( label );

        JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
        slider.addChangeListener(new ChangeListener()
        {
            public void stateChanged(ChangeEvent e)
            {
                int value = slider.getValue();
                BufferedImage rotated = Rotation.rotateImage(bi, Math.toRadians(value) );
                label.setIcon( new ImageIcon(rotated) );
            }
        });

        JFrame frame = new JFrame("Rotation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(wrapper, BorderLayout.CENTER);
        frame.add(slider, BorderLayout.PAGE_END);
        frame.setSize(600, 600);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}
英文:

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

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
public class Rotation
{
public static BufferedImage rotateImage(BufferedImage original, double theta)
{
//  Determine the size of the rotated image
double cos = Math.abs(Math.cos(theta));
double sin = Math.abs(Math.sin(theta));
double width  = original.getWidth();
double height = original.getHeight();
int w = (int)(width * cos + height * sin);
int h = (int)(width * sin + height * cos);
//  Create empty image and fill in background
BufferedImage rotated = new BufferedImage(w, h, original.getType());
Graphics2D g2 = rotated.createGraphics();
g2.setPaint(UIManager.getColor("Panel.background"));
g2.fillRect(0, 0, w, h);
//  Rotate the image
double x = w/2;
double y = h/2;
AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
x = (w - width)/2;
y = (h - height)/2;
at.translate(x, y);
g2.drawRenderedImage(original, at);
g2.dispose();
return rotated;
}
private static void createAndShowGUI()
{
BufferedImage bi;
try
{
String path = "mong.jpg";
ClassLoader cl = Rotation.class.getClassLoader();
bi = ImageIO.read( cl.getResourceAsStream(path) );
}
catch (Exception e) { return; }
JLabel label = new JLabel( new ImageIcon( bi ) );
label.setBorder( new LineBorder(Color.RED) );
label.setHorizontalAlignment(JLabel.CENTER);
JPanel wrapper = new JPanel();
wrapper.add( label );
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
BufferedImage rotated = Rotation.rotateImage(bi, Math.toRadians(value) );
label.setIcon( new ImageIcon(rotated) );
}
});
JFrame frame = new JFrame("Rotation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(wrapper, BorderLayout.CENTER);
frame.add(slider, BorderLayout.PAGE_END);
frame.setSize(600, 600);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}

答案2

得分: -1

尝试

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

Try

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:

确定