Java:旋转图像
我需要能够单独旋转图像(在java中)。到目前为止我唯一发现的是 g2d.drawImage(image, affinetransform, ImageObserver )。不幸的是,我需要在特定点绘制图像,并且没有带有参数的方法:1. 单独旋转图像,2. 允许我设置 x 和 y。任何帮助表示赞赏
I need to be able to rotate images individually(in java). The only thing I have found so far is g2d.drawImage(image, affinetransform, ImageObserver ). Unfortunately, I need to draw the image at a specific point, and there is no method with an argument that 1.rotates the image separately and 2. allows me to set the x and y. any help is appreciated
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(8)
我对现有的答案有点挣扎,因为我要旋转的图像并不总是正方形,此外,接受的答案有一条评论询问“有关如何规避截止问题的任何信息”,但未得到答复。
因此,对于那些在旋转时遇到图像被裁剪问题的人来说,这里的代码对我有用:
public static BufferedImage rotate(BufferedImage bimg, Double angle) {
double sin = Math.abs(Math.sin(Math.toRadians(angle))),
cos = Math.abs(Math.cos(Math.toRadians(angle)));
int w = bimg.getWidth();
int h = bimg.getHeight();
int neww = (int) Math.floor(w*cos + h*sin),
newh = (int) Math.floor(h*cos + w*sin);
BufferedImage rotated = new BufferedImage(neww, newh, bimg.getType());
Graphics2D graphic = rotated.createGraphics();
graphic.translate((neww-w)/2, (newh-h)/2);
graphic.rotate(Math.toRadians(angle), w/2, h/2);
graphic.drawRenderedImage(bimg, null);
graphic.dispose();
return rotated;
}
一种简单的方法,无需使用如此复杂的绘制语句:
//Make a backup so that we can reset our graphics object after using it.
AffineTransform backup = g2d.getTransform();
//rx is the x coordinate for rotation, ry is the y coordinate for rotation, and angle
//is the angle to rotate the image. If you want to rotate around the center of an image,
//use the image's center x and y coordinates for rx and ry.
AffineTransform a = AffineTransform.getRotateInstance(angle, rx, ry);
//Set our Graphics2D object to the transform
g2d.setTransform(a);
//Draw our image like normal
g2d.drawImage(image, x, y, null);
//Reset our graphics object so we can draw with it again.
g2d.setTransform(backup);
public static BufferedImage rotateCw( BufferedImage img )
{
int width = img.getWidth();
int height = img.getHeight();
BufferedImage newImage = new BufferedImage( height, width, img.getType() );
for( int i=0 ; i < width ; i++ )
for( int j=0 ; j < height ; j++ )
newImage.setRGB( height-1-j, i, img.getRGB(i,j) );
return newImage;
}
来自 https://coderanch.com/t/485958/java/Rotating-buffered -图像
这是 90°、180° 和 180° 旋转的解决方案。 270度。
对于这些情况,AffineTransform 可以引入一些损失/插值。
该解决方案是无损的并且是可扩展的。还可以处理(深奥的?)超过 8 位/像素的颜色模型,而 BufferedImage.getRGB(int x, int y) 则不能。
该解决方案在逐像素的基础上进行,其优点是编码简单。
可以逐行读取原始图像以获得性能,但它更复杂,所以我将其省略。
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
/**
* N.B. this example uses the new switch/case/Arrow notation, which requires Java 14.
*/
public enum Rotation {
CLOCKWISE_90,
CLOCKWISE_180,
CLOCKWISE_270;
public BufferedImage rotate(final BufferedImage original) {
final int oW = original.getWidth();
final int oH = original.getHeight();
final BufferedImage rotated =
switch (this) {
case CLOCKWISE_180 -> new BufferedImage(oW, oH, original.getType());
default -> new BufferedImage(oH, oW, original.getType());
};
final WritableRaster rasterOriginal = original.copyData(null);
final WritableRaster rasterRotated = rotated .copyData(null);
/*
* The Data for 1 Pixel...
*/
final int[] onePixel = new int[original.getSampleModel().getNumBands()];
/*
* Copy the Pixels one-by-one into the result...
*/
for (int x = 0; x < oW; x++) {
for (int y = 0; y < oH; y++) {
; rasterOriginal.getPixel( x, y, onePixel);
switch (this) {
case CLOCKWISE_90 -> rasterRotated .setPixel(oH - 1 - y, x, onePixel);
case CLOCKWISE_270 -> rasterRotated .setPixel( y, oW - 1 - x, onePixel);
default -> rasterRotated .setPixel(oW - 1 - x, oH - 1 - y, onePixel);
};
}
}
rotated.setData(rasterRotated);
return rotated;
}
}
抱歉,但是对于我作为图形初学者来说,所有答案都很难理解......
经过一番摆弄,这对我来说很有效,而且很容易推理。
@Override
public void draw(Graphics2D g) {
AffineTransform tr = new AffineTransform();
// X and Y are the coordinates of the image
tr.translate((int)getX(), (int)getY());
tr.rotate(
Math.toRadians(this.rotationAngle),
img.getWidth() / 2,
img.getHeight() / 2
);
// img is a BufferedImage instance
g.drawImage(img, tr, null);
}
我想如果你想旋转一个矩形图像,这个方法不会工作,并且会剪切图像,但我认为你应该创建方形 png 图像并旋转它。
我认为最可靠和最简单的方法不仅是旋转图像,而且还旋转您正在使用的坐标。此代码会将 bufferedImage 围绕左上角旋转并相应地绘制它而不进行裁剪,并且返回的图像将绘制在正确的位置。如果您知道向量和矩阵是什么,并查看维基百科关于旋转矩阵的文章,您将很容易理解这段代码。我还添加了一些手绘图。在算法的第二部分中,我们确定较大矩形的位置和尺寸,其中包含旋转的 bufferedImage。我们定义的前 4 个点在技术上并未使用,但它们仍然可以帮助您了解这些点最初的位置。
public void drawRotated(final Graphics g, final BufferedImage bufferedImage, final int x, final int y, final int width, final int height, final double angle) {
final Rectangle collision = new Rectangle(x, y, width, height);
final BufferedImage resize = resize(bufferedImage, collision.width, collision.height);
final BufferedImage rotate = rotate(resize, angle, collision);
g.drawImage(rotate, collision.x, collision.y, collision.width, collision.height, null);
}
public static BufferedImage resize(final BufferedImage bufferedImage, final int newWidth, final int newHeight) {
final BufferedImage resized = new BufferedImage(newWidth, newHeight, bufferedImage.getType());
final Graphics g = resized.createGraphics();
g.drawImage(bufferedImage, 0, 0, newWidth, newHeight, null);
return resized;
}
public static BufferedImage rotate(final BufferedImage bufferedImage, final double angle, final Rectangle collision) {
final double sin = Math.sin(Math.toRadians(angle));
final double cos = Math.cos(Math.toRadians(angle));
final int x1 = collision.x;
final int y1 = collision.y;
final int x2 = collision.x+collision.width;
final int y2 = collision.y;
final int x3 = collision.x;
final int y3 = collision.y+collision.height;
final int x4 = collision.x+collision.width;
final int y4 = collision.y+collision.height;
//turn all 4 points around the top left point
final int newx1 = collision.x;
final int newy1 = collision.y;
//the y component is 0
final int newx2 = (int) (collision.x+collision.width*cos);
final int newy2 = (int) (collision.y+collision.width*sin);
//the x component is 0
final int newx3 = (int) (collision.x-collision.height*sin);
final int newy3 = (int) (collision.y+collision.height*cos);
final int newx4 = (int) (collision.x+collision.width*cos-collision.height*sin);
final int newy4 = (int) (collision.y+collision.width*sin+collision.height*cos);
//determine the new position of our bigger rectangle containing our image
collision.x = Math.min(Math.min(newx1, newx2), Math.min(newx3, newx4));
collision.y = Math.min(Math.min(newy1, newy2), Math.min(newy3, newy4));
//determine the new dimensions of our bigger rectangle containing our image
collision.width = Math.max(Math.max(newx1, newx2), Math.max(newx3, newx4))-collision.x;
collision.height = Math.max(Math.max(newy1, newy2), Math.max(newy3, newy4))-collision.y;
final BufferedImage rotated = new BufferedImage(collision.width, collision.height, bufferedImage.getType());
final Graphics2D g2d = rotated.createGraphics();
g2d.translate(newx1- collision.x, newy1- collision.y);
g2d.rotate(Math.toRadians(angle), 0, 0);
g2d.drawRenderedImage(bufferedImage, null);
g2d.dispose();
return rotated;
}
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
您可以这样做。此代码假设存在名为“image”的缓冲图像(就像您的评论所说)
This is how you can do it. This code assumes the existance of a buffered image called 'image' (like your comment says)