Java 2D 旋转 BufferedImage

Java 2D rotate BufferedImage

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

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

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

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

我希望看到的是: Expected

谢谢!

尝试

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

这是一个更通用的解决方案,它允许旋转任何指定的度数:

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