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



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

这是我目前在绘制函数中的内容。Renderable是一个预加载的buffereimage。

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整除时

有什么我错过了或应该做不同的?在我看来,图像正在丢失数据。传入函数的Graphics2D对象与用于渲染方格后面的线条的对象相同,并且应该覆盖整个画布,即800x600像素。

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

最新更新