【问题标题】:AffineTransformOp speed/memory questionAffineTransformOp 速度/内存问题
【发布时间】:2009-12-03 17:44:53
【问题描述】:

我以前曾问过这个问题,但我想重新表述/澄清一些观点并对其进行扩展。我有一段代码使用 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);

但是,这比第一个版本要慢得多。我想要第一个版本的速度和第二个版本的内存使用率。

  1. 第一个版本后如何清理?具体来说,中间的 BufferedImage 存储在哪里,如何删除它们?
  2. 为什么第二个版本比第一个慢?我该怎么做才能加快速度?

感谢您的帮助!!!

【问题讨论】:

  • 您真的遇到 OutOfMemoryErrors 了吗?如果不是,那么这只是 GC 何时收集对象的问题,而不是实际的内存泄漏。

标签: java filter affinetransform


【解决方案1】:

您如何获得displayImage 以及它使用的是什么ColorModel

如果是IndexColorModel,那可以解释很多。

第一个代码片段将使用DirectColorModel 返回BufferedImage。这将需要每个像素 4 个字节,而索引图像通常每个像素需要 1 个字节。 1:4 扩展可能会导致您的内存不足。

第二个代码片段创建了一个与源代码相同模型的BufferedImage。当这是一个IndexColorModel 并且插值不是NEAREST_NEIGHBOR 时,filter() 调用将创建一个带有DirectColorModel 的临时BufferedImage。它将使用它作为过滤操作的目标,然后重新量化临时缓冲区并将其绘制到您的displayImage2 中。所以,bitblit 的数量是原来的两倍。

如果您只进行一次转换,我会说使用第二种形式。

如果您正在执行多项操作,请分配一对BufferedImages 和DirectColorModel。大到足以容纳您最大的图像。将您的源图像绘制到其中一个中,并在它们之间来回执行您的过滤器。然后当你完成后,使用ColorConvertOp 重新量化回索引图像。这样,您只需进行一次颜色转换,而不是每次调用过滤器。

【讨论】:

  • 我想我会先尝试您的第二个建议,您能告诉我如何使用 ColorConvertOp 将直接颜色模型转换为索引颜色模型吗?
  • ColorConvertOp 的工作方式与 AffineTransformOp 类似,但您需要调用 filter(src, dst) 传递 dst 作为所需颜色模型的现有 BufferedImage
  • 好的,但是如何使用 ColorConvertOp 中的构造函数。我做了以下 ColorModel indexColorModel = displayImage.getColorModel(); displayImage = op.filter(displayImage, null); ColorConvertOp colorOp = new ColorConvertOp(indexColorModel.getColorSpace(), displayImage.getColorModel().getColorSpace(), null); displayImage = colorOp.filter(displayImage, null);当我运行它时,它只会挂在过滤线上,永远不会返回。
  • 对不起,我打错了上面的代码行,它实际上应该是 ColorModel indexColorModel = displayImage.getColorModel(); displayImage = op.filter(displayImage, null); ColorConvertOp colorOp = new ColorConvertOp(displayImage.getColorModel().getColorSpace(), indexColorModel.getColorSpace(), null); displayImage = colorOp.filter(displayImage, null);我在 ColorConvertOp 构造函数中混淆了参数的顺序,但它仍然非常慢。
  • 我一直使用简单的“仅提示”构造函数:ColorConvertOp colorOp = ColorConvertOp (null);然后传入具有目标所需颜色空间的 BI。
【解决方案2】:

我同意以下评论,除非您收到 OutOfMemoryErrors,否则这是正常现象,GC 将在其认为合适的时候收集图像。这是我有时在担心时做的一个愚蠢的测试:将其放入主函数中的循环并观察分析器中的内存使用情况(它应该形成类似之字形的模式或其他东西)但并不总是能够完成成功。

【讨论】:

  • 我遇到了内存不足的问题。当内存太高时,我可以通过运行 System.finalization 和 System.gc 来减慢它(我有一个跟踪内存管理的线程)。
  • 如果你现在让它工作,那很好,虽然我担心你有一个线程跟踪内存管理 - 这就像你试图重新创建 Java 的内存管理并且它不会'反正也不会那么好。这听起来很傻,但是你没有在堆上分配足够的空间吗?当我使用大量图像转换时,我认为必须分配 512 或 1024,才能获得舒适的用户体验。您还可以在 JVM 中设置许多与内存和 GC 相关的参数 - 试试这里:java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html
猜你喜欢
  • 2012-02-10
  • 2022-12-30
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 2011-05-15
  • 2011-11-13
  • 1970-01-01
相关资源
最近更新 更多