繁体   English   中英

如何在 Java 中旋转和绘制 BufferedImage?

[英]How do I rotate and draw a BufferedImage in Java?

我正在尝试为一个小项目开发一个小的渲染东西。 我已经到了可以设置 Graphics2D object 并从简单的 render() 循环中调用的地方,但是当尝试在适当的位置绘制图像时,图像会笨拙地裁剪并开始丢失数据。

这就是我目前在抽奖 function 中的内容。 Renderable 是一个预加载的 BufferedImage。

    public void draw(Graphics2D g2d, int x, int y, int scale, int rotation) {
        scale = scale / 2;
        
        AffineTransform at = new AffineTransform();
        at.rotate(Math.toRadians(rotation), renderable.getWidth() / 2, renderable.getHeight() / 2);
        AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
        
        BufferedImage copy = op.filter(renderable, null);
                
        int pX = (400 - ((copy.getWidth() * scale) / 2)) + x;
        int pY = (300 - ((copy.getHeight() * scale) / 2)) + y;      
        
        g2d.drawImage(copy, pX, pY, copy.getWidth() * scale, copy.getHeight() * scale, null);
    }

当旋转不能被 90 整除时

当旋转可被 0、90、180 或 270 整除时

我有什么遗漏或应该做不同的事情吗? 在我看来,图像正在丢失数据。 传递给 function 的 Graphics2D object 与用于渲染方格方块后面的线相同,应该覆盖整个 Z6EA5359E01A41842884943125508289BZ 像素,即

更新

        int rotation = 0;
        
        while (EngineGlue.isValid()) {
            rotation = rotation + 15;
            if (rotation >= 360) {
                rotation = 0;
            }
            
            Graphics2D g2d = (Graphics2D)EngineGlue.getInstance().getCanvas().getBufferStrategy().getDrawGraphics();
            g2d.clearRect(0, 0, 800, 600);
            
            g2d.drawLine(0, 300, 800, 300);
            g2d.drawLine(400, 0, 400, 600);
                        
            //ta1.draw(g2d, -100, 0, 2, rotation);
            //ta2.draw(g2d, 100, 0, 3, -rotation);
            ta3.draw(g2d, 0, 0, 1, rotation);
            
            EngineGlue.getInstance().getCanvas().getBufferStrategy().show();
            Thread.sleep(150);
        }
            frame = new JFrame(title);
            canvas = new Canvas();
            
            frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
            frame.setResizable(false);
            frame.setVisible(true);
            frame.add(canvas);
            frame.pack();
            frame.setSize(EngineGlue.Dimension.WIDTH.getValue(), EngineGlue.Dimension.HEIGHT.getValue());
            frame.setLocationRelativeTo(null);
            
            canvas.setSize(EngineGlue.Dimension.WIDTH.getValue(), EngineGlue.Dimension.HEIGHT.getValue());
            canvas.createBufferStrategy(3);

您可以使用AffineTransform来旋转和缩放图像:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.awt.geom.*;
import java.awt.image.*;

public class RotateAndScale extends JPanel
{
    private Image image;

    public RotateAndScale(Image image)
    {
        this.image = image;
    }

    @Override
    protected void paintComponent(Graphics g)
    {
         super.paintComponent(g);

         // create the transform, note that the transformations happen
         // in reversed order (so check them backwards)
         AffineTransform at = new AffineTransform();

         // 4. translate it to the center of the component
         at.translate(getWidth() / 2, getHeight() / 2);

         // 3. do the actual rotation
         at.rotate(Math.toRadians(45));

         // 2. scale the image
         at.scale(0.5, 0.5);

         // 1. translate the object to rotate around the center
         at.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);

         // draw the image
         Graphics2D g2d = (Graphics2D) g;
         g2d.drawImage(image, at, null);

         // continue drawing other stuff (non-transformed)
         //...
    }

    private static void createAndShowGUI()
    {
        try
        {
            BufferedImage image = ImageIO.read(new File("splash.gif"));

            JFrame frame = new JFrame("SSCCE");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( new RotateAndScale(image));
            frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
            frame.setSize(400, 400);
            frame.setLocationByPlatform( true );
            frame.setVisible( true );
        }
        catch(Exception e) { System.out.println(e); }
    }

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

以上是我很久以前在某处找到的代码。

如果您只想旋转图像,最简单的方法是旋转图形上下文而不是图像本身。 这会读取Mars的图像,因此您必须替换自己的图像。

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class RotateImage extends JPanel {
    
    JFrame frame;
    int width;
    int height;
    
    BufferedImage b = null;
    String imageFile = "f:/redmarble.jpg";

    public RotateImage() {
        frame = new JFrame();
        setPreferredSize(new Dimension(width, height));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new RotateImage().startup());
    }
    
    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }
    
    public void startup() {
        try {
            b = ImageIO.read(new File(imageFile));
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
       // calculate the diagonal of the image to size the panel
       // this allows all rotations to fit within the panel
        double diag = Math.hypot(b.getHeight(), b.getWidth());      
        width = (int) diag;
        height = (int) diag;
        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        repaint();
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (b == null) {
            return;
        }
        
        Graphics2D g2d = (Graphics2D) g.create();
        
        // set the angle of rotation and the center of rotation to the middle of the
        // panel - width and height are equal but I still like to reference them
        // independently (could save debugging time in the future).
        g2d.rotate(Math.toRadians(45), width/2, height/2);
        
        // now draw the image, adjusting  x,y starting point to ensure rotation
        // about the center.
        g2d.drawImage(b, (width-b.getWidth())/2, (height-b.getHeight())/2,null);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM