我以前曾问过这个问题,但我想重新阐明/澄清一些观点并对其进行扩展。我有一段代码使用AffineTransform转换BufferedImage。
op = new AffineTransformOp(atx, interactive ? interpolationInteractive : interpolationNormal);
displayImage = op.filter(displayImage, null);
此代码工作正常,但它会导致内存累积。具体来说,每次调用这段代码时都会存储更多内存。我也尝试过其他形式的过滤器。
op = new AffineTransformOp(atx, interactive ? interpolationInteractive : interpolationNormal);
displayImage2 = op.createCompatibleDestImage(displayImage, displayImage.getColorModel());
op.filter(displayImage, displayImage2);
但是,这比第一个版本要慢得多。我希望第一个版本的速度与第二个版本的内存使用速度相同。
感谢您的帮助!!!
答案 0 :(得分:0)
我同意评论,除非你得到OutOfMemoryErrors,否则这是正常的事情,GC会在它认为合适时收集图像。这是一个愚蠢的测试,当我有一个问题时我有时做了:把它放在一个主函数的循环中,并在一个分析器中观察内存使用情况(它应该形成一个类似Z字形的模式或者其他东西)但是并不总是能够完成成功。
答案 1 :(得分:0)
您如何获得displayImage
以及ColorModel
使用的是什么?
如果是IndexColorModel
,可能会解释很多。
第一个代码片段将使用BufferedImage
返回DirectColorModel
。对于索引图像,这将需要每像素4个字节,而每像素通常需要1个字节。 1:4的扩展可能导致你的内存不足。
第二个代码片段使BufferedImage
与源具有相同的模型。当该值为IndexColorModel
且插值不是NEAREST_NEIGHBOR
时,filter()
调用将创建一个BufferedImage
的临时DirectColorModel
。它将使用它作为过滤器操作的目标,然后重新量化临时缓冲区并将其绘制到displayImage2
中。所以,bitblits的数量是原来的两倍。
如果你只进行一次转换,我会说第二种形式。
如果您正在进行多项操作,请分配一对BufferedImage
和DirectColorModel
。大到足以容纳你最大的形象。将源图像绘制到其中一个中,然后在它们之间来回执行过滤。然后,当您完成后,使用ColorConvertOp
重新量化回索引图像。这样,您只需要进行一次颜色转换,而不是每次过滤调用。