尽可能快地清除透明的BufferedImage

12

我有一个通过以下代码创建的透明BufferedImage(如何创建不重要,我认为):

            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();

            Rectangle screen = transformationContext.getScreen();

            // Create an image that supports transparent pixels
            return gc.createCompatibleImage((int) screen.getWidth(), (int) screen.getHeight(),
                    Transparency.BITMASK);

如何以最快的方式清除图像(将其清空,使其与创建时相同状态),而不必重新创建图像?重新创建图像会给GC带来负担,导致VM暂停并冻结UI。

2个回答

20

明白了 :) 使用 clearRect 代替使用透明颜色的填充。

            graphics = (Graphics2D) offlineBuffer.getGraphics();
            graphics.setBackground(new Color(255, 255, 255, 0));
            Rectangle screen = transformationContext.getScreen();
            graphics.clearRect(0,0, (int)screen.getWidth(), (int)screen.getHeight());

6
据说自1.1版本以来,clearRect已被弃用,尽管它没有被标记为弃用(可能是因为注释还不存在吗?)。现在的首选方法是:graphics.setComposite(AlphaComposite.Clear); graphics.fillRect(0, 0, SIZE, SIZE); graphics.setComposite(AlphaComposite.SrcOver);(假设你之前使用的合成方式是SrcOver,并且这是默认设置)。这实际上与clearRect的实现非常接近。 - Mark Jeronimus
Java文档中没有废弃标签,因此我推测它仍然有效。 - adrian.tarau
@adrian.tarau 他所指的是注释。Javadocs 是自动生成的;由于 @Deprecated 注释不在代码中(它还不存在),因此也不在 Javadocs 中。 - Qix - MONICA WAS MISTREATED
这个可以工作,但是当启用抗锯齿时,所选择的背景颜色似乎会影响文本渲染。我使用 new Color(0, 0, 0, 0) 得到了更好的结果。 - Emmanuel Bourg

9

有一种相对较快的方法,但我不确定它是否是最快的(我想看看其他答案),就是拥有另一张你从未修改过且始终“完全清除” / “完全透明”的图片,然后进行光栅复制,比如你给那个副本命名为CLEAR:

imageYouWantToClear.setData( CLEAR.getRaster() );

请注意,在处理图形时,性能可能会非常棘手,因为有许多不太好记录的行为。例如,您的图像(比如CLEAR)可能已经硬件加速,但是一旦使用了可变方法(比如setRgb()),就会失去硬件加速,并且很难意识到您刚刚失去了硬件加速的好处。
我认为寻找关于高性能BufferedImage的信息的最佳地方应该在Java游戏程序员和Java游戏API程序员社区/论坛中。
顺便说一下,请确保您的两个BufferedImage都使用“兼容”模式:TYPE_INT_ARGB可能在Windows上很好,但在OS X上可能不行,因此您需要创建它们做以下操作:
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);

哎呀,Demeter法则真的很痛苦,Java谢谢你;)


感谢WizardOfOdds,但是保留另一张图片(当"active"图像重新创建时需要重新创建该图像,因为边界发生了变化)将增加内存使用量(考虑到1600x1200屏幕分辨率)。 clearRect能解决问题,而且似乎非常快。 - adrian.tarau
我在Windows 10上尝试了Java 8,但速度比“clearRect()”慢了约50倍。 - Emmanuel Bourg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接