图像旋转方法在内存中留下一些东西
image rotation method leaves something in the ram
我目前正在开发一款游戏,为了获得更多样化的图形,我想调用 rotate(BufferedImage imgOld, int deg) 方法数百次来旋转一些图形(例如树桩)。
对于未旋转的图形,我从未遇到过任何内存问题。但是,一旦我开始使用旋转器,如果我没有大幅减少旋转图像的数量(比如大幅减少 95%),就会发生错误。
错误总是发生在 rotate(BufferedImage imgOld, int deg) 方法内部,并且只是因为我开始旋转大量图像,所以我想内存中一定有一些来自 rotate(BufferedImage imgOld, int deg) 方法我不知道怎么处理。
在这里你可以看到 class 旋转器的代码:
package movement;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
public class Rotator {
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //Parameters for the method are the image to rotate and the rate of rotation in degrees
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(deg), (int)(imgOld.getWidth()/2), (int)(imgOld.getHeight()/2)); //setting up the transform
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //creating a new image with the same properties of the old one
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create my graphics
g.setTransform(at); //applying the transform
g.drawImage(imgOld, 0, 0, null); //painting rotated image
return imgNew; //return rotated image
}
}
我希望有人有想法并且我没有犯任何错误(这是我在这里发布的第一个问题)。
您最大的问题很简单 - 您正在复制 每 个图像,您 每 次旋转。您可以尝试将旋转后的图像绘制回自身,从而无需为垃圾收集器搅动大量对象。
此外,如果您执意要制作新对象,请确保冲洗 (BufferedImage#flush
) 旧图像并丢弃 (Graphics2D#dispose
) 图形对象。
您使用的工具错误。如果你想转换整个图像,尤其是。 BufferedImage
s,你应该看看BufferedImageOp
s and in your case AffineTransformOp
。
那么整个操作可以实现为
public static BufferedImage rotate(BufferedImage imgOld, int deg){
AffineTransform at = AffineTransform.getRotateInstance(
Math.toRadians(deg), imgOld.getWidth()/2, imgOld.getHeight()/2);
AffineTransformOp op=new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
BufferedImage imgNew = new BufferedImage(
imgOld.getWidth(), imgOld.getHeight(), imgOld.getType());
return op.filter(imgOld, imgNew);
}
这不涉及 Graphics
之类的。您最初的方法是旋转原始图像并将其绘制到目标图像上,方法是将目标的原始内容(最初为空)与源的旋转数据相结合,具体取决于 Graphics
混合模式。相比之下,上面的代码会将转换后的图片直接渲染到目标中,而不是试图保留现有内容。
进一步注意,您可以传入现有图像以供重复使用。 BufferedImageOp.filter
支持 null
目标图像参数以创建新的兼容图像,但 AffineTransformOp
会创建比源图像更大的角度,例如 45°,这似乎不是您想要的,给出你问题中的代码。
我目前正在开发一款游戏,为了获得更多样化的图形,我想调用 rotate(BufferedImage imgOld, int deg) 方法数百次来旋转一些图形(例如树桩)。
对于未旋转的图形,我从未遇到过任何内存问题。但是,一旦我开始使用旋转器,如果我没有大幅减少旋转图像的数量(比如大幅减少 95%),就会发生错误。
错误总是发生在 rotate(BufferedImage imgOld, int deg) 方法内部,并且只是因为我开始旋转大量图像,所以我想内存中一定有一些来自 rotate(BufferedImage imgOld, int deg) 方法我不知道怎么处理。
在这里你可以看到 class 旋转器的代码:
package movement;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
public class Rotator {
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //Parameters for the method are the image to rotate and the rate of rotation in degrees
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(deg), (int)(imgOld.getWidth()/2), (int)(imgOld.getHeight()/2)); //setting up the transform
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //creating a new image with the same properties of the old one
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create my graphics
g.setTransform(at); //applying the transform
g.drawImage(imgOld, 0, 0, null); //painting rotated image
return imgNew; //return rotated image
}
}
我希望有人有想法并且我没有犯任何错误(这是我在这里发布的第一个问题)。
您最大的问题很简单 - 您正在复制 每 个图像,您 每 次旋转。您可以尝试将旋转后的图像绘制回自身,从而无需为垃圾收集器搅动大量对象。
此外,如果您执意要制作新对象,请确保冲洗 (BufferedImage#flush
) 旧图像并丢弃 (Graphics2D#dispose
) 图形对象。
您使用的工具错误。如果你想转换整个图像,尤其是。 BufferedImage
s,你应该看看BufferedImageOp
s and in your case AffineTransformOp
。
那么整个操作可以实现为
public static BufferedImage rotate(BufferedImage imgOld, int deg){
AffineTransform at = AffineTransform.getRotateInstance(
Math.toRadians(deg), imgOld.getWidth()/2, imgOld.getHeight()/2);
AffineTransformOp op=new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
BufferedImage imgNew = new BufferedImage(
imgOld.getWidth(), imgOld.getHeight(), imgOld.getType());
return op.filter(imgOld, imgNew);
}
这不涉及 Graphics
之类的。您最初的方法是旋转原始图像并将其绘制到目标图像上,方法是将目标的原始内容(最初为空)与源的旋转数据相结合,具体取决于 Graphics
混合模式。相比之下,上面的代码会将转换后的图片直接渲染到目标中,而不是试图保留现有内容。
进一步注意,您可以传入现有图像以供重复使用。 BufferedImageOp.filter
支持 null
目标图像参数以创建新的兼容图像,但 AffineTransformOp
会创建比源图像更大的角度,例如 45°,这似乎不是您想要的,给出你问题中的代码。