gpt4 book ai didi

java - 如何在 Java 中旋转非正方形图像?

转载 作者:搜寻专家 更新时间:2023-11-01 02:24:24 24 4
gpt4 key购买 nike

我最近看到this question关于如何在 Java 中旋转图像。我直接从那个答案复制/粘贴它。在实现时,它似乎只旋转正方形的图像(即具有相同的大小、宽度和高度)。当我尝试将它用于非正方形图像时,它似乎切断了使它成为矩形的部分,如果这有意义的话。像这样

我该如何解决/解决这个问题?

编辑:我正在使用的代码。另外,我不会有滚动条,因为这将是一个“游戏”,也不会一直全屏显示。

public class Player extends Entity { //Entity has basic values such as (float) x & y values, along with some getters and setters
double theta;

Reticle reticle; //draws a reticle where the cursor was(basically just replaces java.awt.Cursor due to something not neccessary for me to get into)
Sprite currentImage; //basically just a BufferedImage that you can apply aspect ratios to

//constructor

@Override
public void tick() {
//(this line) gets the Reticle from the main-method class and set it to this reticle object
reticleX = reticle.getX(); //basically gets the mouse coordinates
reticleY = reticle.getY();

x += dX; //delta or change in X
y += dY //delta or change in Y

checkCollision(); //bounds checking

//getCentralizedX()/Y() gets the center of the currentImage
theta = getAngle(getCentralizedX(), getCentralizedY(), reticleX, reticleY);

currentImage = Images.rotateSprite(currentImage, theta);
}

@Override
public void render(Graphics g) {
currentImage.render(g, x, y);
g.drawLine((int) getCentralizedX(), (int) getCentralizedY(), (int) reticleX, (int) reticleY);
}

public double getAngle(float startX, float startY, float goalX, float goalY) {
double angle = Math.atan2(goalY - startY, goalX - startX);
//if(angle < 0) { //removed this as this was the thing messing up the rotation
//angle += 360;
//}
}

如果士兵的角度是 90 < 角度 < 270,那么它(基本上)是,但是,如果它的 90 > 角度 > 270,那么它会有点不稳定。这里有一些照片。错误的不是瞄准线(蓝线)的角度。

删除了所有图像,因为删除了 if(angle < 0) getAngle() 内部修复了旋转错误。现在唯一的问题是它没有原地旋转。

编辑 2:我的 SSCCE,它使用与我的游戏相同的方法,但由于某种原因出现异常。

public class RotateEx extends Canvas implements Runnable {
Player player;

public RotateEx(BufferedImage image) {
player = new Player(image, 50, 50);
setPreferredSize(new Dimension(600, 600));
}

public void setDegrees(int degrees) {
player.theta = Math.toRadians(degrees);
}

public 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 out = new BufferedImage(w, h, original.getType());
Graphics2D g2 = out.createGraphics();
double x = w / 2; //the middle of the two new values
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 out;
}

public void tick() {
player.tick();
}

public void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(4);
return;
}

Graphics g = bs.getDrawGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
player.render(g);

g.dispose();
bs.show();
}

public static void main(String args[]) throws IOException, InterruptedException {
String loc = "FILELOCATION"; //of course this would be a valid image file
BufferedImage image = ImageIO.read(new File(loc));

final RotateEx ex = new RotateEx(image);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
ex.setDegrees(value);
}
});

JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(ex);
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);

new Thread(ex).start();
}

@Override
public void run() {
long lastTime = System.nanoTime();
final double numTicks = 60.0;
double n = 1000000000 / numTicks;
double delta = 0;
int frames = 0;
int ticks = 0;
long timer = System.currentTimeMillis();

while (true) {
long currentTime = System.nanoTime();
delta += (currentTime - lastTime) / n;
lastTime = currentTime;

render();
tick();
frames++;

if (delta >= 1) {
ticks++;
delta--;
}
}
}

class Player {
public float x, y;
int width, height;
public double theta; //how much to rotate, in radians
BufferedImage currentImage; //this image would change, according to the animation and what frame its on

public Player(BufferedImage image, float x, float y) {
this.x = x;
this.y = y;
width = image.getWidth();
height = image.getHeight();
currentImage = image;
}

public void tick() {
currentImage = rotateImage(currentImage, theta);
}

public void render(Graphics g) {
g.drawImage(currentImage, (int) x, (int) y, 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.*;

public class Rotation
{
BufferedImage image;
JLabel label;

public Rotation(BufferedImage image)
{
this.image = image;
}

private BufferedImage getImage(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 = image.getWidth();
double height = image.getHeight();
int w = (int)(width * cos + height * sin);
int h = (int)(width * sin + height * cos);

// Rotate and paint the original image onto a BufferedImage

BufferedImage out = new BufferedImage(w, h, image.getType());
Graphics2D g2 = out.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(image, at);
g2.dispose();
return out;
}

private JLabel getLabel()
{
ImageIcon icon = new ImageIcon(image);
label = new JLabel(icon);
label.setHorizontalAlignment(JLabel.CENTER);
return label;
}

private JSlider getSlider()
{
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
BufferedImage bi = getImage(Math.toRadians(value));
label.setIcon(new ImageIcon(bi));
}
});
return slider;
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
String path = "mong.jpg";
ClassLoader cl = Rotation.class.getClassLoader();
BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
Rotation r = new Rotation(bi);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(r.getLabel()));
f.getContentPane().add(r.getSlider(), "South");
f.pack();
f.setLocation(200,200);
f.setVisible(true);
}
catch(IOException e)
{
System.out.println(e);
}
}
});
}
}

编辑:

另一种选择是创建一个图标,然后您可以使用 Rotated Icon .然后你可以在你的绘画代码中旋转和绘画图标。像这样的东西:

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.*;

public class Rotation3 extends JPanel
{
private Icon icon;
private Icon rotated;
private int degrees;

public Rotation3(BufferedImage image)
{
icon = new ImageIcon( image );
setDegrees( 0 );
setPreferredSize( new Dimension(600, 600) );
}

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

double radians = Math.toRadians( degrees );
rotated = new RotatedIcon(icon, degrees);

// translate x/y so Icon is rotated around a specific point (300, 300)

int x = 300 - (rotated.getIconWidth() / 2);
int y = 300 - (rotated.getIconHeight() / 2);
rotated.paintIcon(this, g, x, y);

g.setColor(Color.RED);
g.fillOval(295, 295, 10, 10);
}

public void setDegrees(int degrees)
{
this.degrees = degrees;
double radians = Math.toRadians( degrees );
rotated = new RotatedIcon(icon, degrees);
repaint();
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
String path = "dukewavered.gif";
ClassLoader cl = Rotation3.class.getClassLoader();
BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
final Rotation3 r = new Rotation3(bi);

final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});

JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
catch(IOException e)
{
System.out.println(e);
}
}
});
}
}

编辑 2:

这里有一个比我想象的更简单的例子:

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

public class Rotation2 extends JPanel
{
BufferedImage image;
int degrees;
int point = 250;

public Rotation2(BufferedImage image)
{
this.image = image;
setDegrees( 0 );
setPreferredSize( new Dimension(600, 600) );
}

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

Graphics2D g2 = (Graphics2D)g.create();

double radians = Math.toRadians( degrees );
g2.translate(point, point);
g2.rotate(radians);
g2.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
g2.drawImage(image, 0, 0, null);

g2.dispose();

g.setColor(Color.RED);
g.fillOval(point - 5, point - 5, 10, 10);
}

public void setDegrees(int degrees)
{
this.degrees = degrees;
repaint();
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
// String path = "mong.jpg";
String path = "dukewavered.gif";
ClassLoader cl = Rotation2.class.getClassLoader();
BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
final Rotation2 r = new Rotation2(bi);

final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});

JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
catch(IOException e)
{
System.out.println(e);
}
}
});
}
}

旋转代码取自:How to rotate an image gradually in Swing?

关于java - 如何在 Java 中旋转非正方形图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28755136/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com