【问题标题】:Clear a transparent BufferedImage as fast as possible尽快清除透明的 BufferedImage
【发布时间】:2011-01-22 23:12:49
【问题描述】:

我使用以下代码创建了一个透明的 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。

【问题讨论】:

    标签: java awt bufferedimage graphics2d


    【解决方案1】:

    知道了 :) 使用 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());
    

    【讨论】:

    • clearRect 据说自 1.1 以来已被弃用,尽管它没有被标记为这样(可能是因为注释还不存在?)。现在首选的方式是:graphics.setComposite(AlphaComposite.Clear); graphics.fillRect(0, 0, SIZE, SIZE); graphics.setComposite(AlphaComposite.SrcOver);(假设 SrcOver 是您之前使用的组合,并且是默认值)这实际上接近于 clearRect 的实现。
    • java doc中没有弃用标签,所以我认为它仍然有效
    • @adrian.tarau 这就是他所指的;注释。 javadocs 是自动生成的;因为 @Deprecated 注释不在代码中(它还不存在),所以它不在 javadocs 中。
    • 这行得通,但似乎文本渲染受启用抗锯齿时选择的背景颜色的影响。我使用new Color(0, 0, 0, 0) 得到了更好的结果。
    【解决方案2】:

    一种相对较快的方法,但我不知道它是否最快(我希望看到其他答案)是拥有另一张您从不修改且始终“完全清除”/“完全透明”的图片" 然后你做了一个光栅副本,假设你把那个副本命名为 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);
    

    哎呀,得墨忒耳法则很痛,感谢 Java ;)

    【讨论】:

    • 感谢 WizardOfOdds,但保留另一个图像(在重新创建“活动”图像时需要重新创建,因为边界发生变化)会增加内存使用量(考虑 1600x1200 屏幕分辨率)。 clearRect 可以解决问题,而且看起来相当快。
    • 我在 Windows 10 上使用 Java 8 进行了尝试,但这比 clearRect() 慢了约 50 倍。
    猜你喜欢
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多