【问题标题】:Graphics.drawImage() in Java is EXTREMELY slow on some computers yet much faster on othersJava 中的 Graphics.drawImage() 在某些计算机上非常慢,但在其他计算机上却快得多
【发布时间】:2009-03-18 12:31:09
【问题描述】:

我遇到了一个奇怪的问题,基本上是在 Java 中 Graphics.drawImage() 在某些计算机上非常慢,而在其他计算机上则更快。这也与计算机的能力无关,一些较弱的计算机运行良好,而一些较强的计算机似乎在 drawImage 调用中窒息。

它可能与宽度和高度有关,也可能无关,我定义了一个非常非常大的宽度和高度(例如 5000 x 2500)。我认为这不是问题,除非我说它在某些计算机上以实时速度运行,而在其他计算机上运行较慢,并且似乎与计算机的相对功率无关。

两台计算机的 Java 版本相同,都使用 Vista。一个有 1.83ghz Core 2 Duo,1gb RAM 和板载图形(运行一切正常),另一个有 2.53ghz core 2 duo,9600GS(最新的 nVidia 驱动程序)和 4gb 内存,它在 drawImage 调用上确实突兀。

有什么想法吗?

编辑:好的,这真的很奇怪,我正在将图像绘制到 Swing 中的窗口,现在当我调整窗口大小并使其非常小时,图像也会缩小并且变得很小。突然间一切都运行得很顺利,当我将它放大到它仍然运行顺利之前的大小时!

它也有多个显示器问题,如果我使用调整大小技巧使其在一个显示器上运行得更快,然后当超过一半的窗口位于新显示器中时,它会再次开始运行时将其滚动到另一台显示器。我必须再次将窗口大小调整为小然后恢复到原来的大小才能恢复速度。

如果我在一台显示器上进行调整大小技巧,将它移到另一台显示器上,它当然会突突,但如果我将它放回我进行调整大小技巧的原始显示器,它会 100% 工作

如果我打开了两个摆动窗口(显示相同的图像),它们都会运行缓慢,但如果我在一个窗口上执行调整大小技巧,它们都会开始平稳运行(但情况并非总是如此)。

*当我说调整窗口大小时,我的意思是让它尽可能小到实际无法看到图像的程度。

这可能是 Java 中的错误吗?

【问题讨论】:

  • 是什么镜像,电脑上的JDK是什么版本的?
  • 我想我看到了同样的问题。这是 XP 上的 JDK 8(是的,我知道)和一个 Hi-Color 显示器。渲染一个包含全屏截图的 BufferedImage 需要几秒钟的时间 - 但只需要第二次 (!) 绘制组件的时间。对 drawImage 的后续调用又是即时的。也许一些转换发生在内部?总而言之相当令人困惑,而且简单的颜色转换需要那么长时间(如果这是原因的话)是不可接受的。

标签: java graphics


【解决方案1】:

将图像写入屏幕的性能在很大程度上受图像存储格式的影响。如果格式与屏幕内存所需的格式相同,则可以非常快;如果不是,则必须进行转换,有时逐个像素地进行转换,这非常慢。

如果您对图像的存储方式有任何控制权,则应将其存储为屏幕正在查找的格式。下面是一些示例代码:

    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice device = env.getDefaultScreenDevice();
    GraphicsConfiguration config = device.getDefaultConfiguration();
    BufferedImage buffy = config.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
    Graphics g = buffy.getGraphics();

如果您要多次绘制图像,则可能值得将其转换为兼容格式,即使它采用其他格式。

如果您在绘制时对其进行转换,则绘制图像也会变慢,您描述中的“调整大小”部分让我认为您可能会这样。同样,调整一次大小(当窗口调整大小时)并缓存调整大小和兼容的图像,以便可以快速重绘。

【讨论】:

  • 这对我来说非常有用,谢谢!我将此代码与 getRGB / setRGB 一起使用来转换我的 BufferedImage
  • 非常感谢!很好的答案,对我帮助很大。考虑接受它。
  • 非常感谢您!从 ~17fps 到 40
  • 我看到您正在使用createCompatibleImage 创建一个BufferedImage,但是然后呢?那只会给您一个空白图像,对吗?你如何将一个 png 文件加载到 BufferedImage 中?
  • @nullromo 我想通了。您可以简单地使用Graphics g = buffy.getGraphics(),然后使用g.draw~~~()
【解决方案2】:

如果您使用的是 sun 的 Java,请尝试以下一些系统属性,作为命令行参数或 main 中的第一行

sun.java2d.opengl=true //强制 ogl sun.java2d.ddscale=true //仅在使用direct3d时 sun.java2d.translaccel=true //仅在使用direct3d时

更多标志可以在this page查看

查看sun.java2d.trace,它可以让您确定图形性能不佳的原因。

【讨论】:

    【解决方案3】:

    这里有几件事可能会影响性能:

    • 可用内存
    • CPU 速度
    • 显卡(板载或单独)
    • 图形驱动程序
    • Java 版本
    • 使用的视频模式(分辨率、位深度、加速支持)

    编辑: 看看编辑过的问题,我建议检查 9600GS 系统是否安装了最新的 NVIDIA 驱动程序。我最近为英特尔板载显卡安装了一个驱动程序,该驱动程序取代了通用的 Windows 驱动程序,使移动窗口、观看视频、浏览等变得更快。

    所有其他规格看起来都不错。也许Java没有检测到9600GS,也没有使用硬件加速,但我对此表示怀疑。

    同时检查操作系统配置。在 Windows 上,您可以关闭硬件加速以进行调试。

    当然,处理此问题的最佳方法是更改​​您的代码 - 调整图像大小或按照 DNS 建议将其拆分为块。您将永远无法看到屏幕上的整个图像。

    【讨论】:

    • 一台电脑很旧,我们说的是真的很旧,另一台是新的和高端的,它有更好的 CPU、RAM、图形,但 Java 版本相同。另外我可能对 50,000x25,000 有误,实际上是 5000x2500。
    【解决方案4】:

    您如何判断计算机的性能? 50x25 K 32 位图像需要超过 4.5 GB RAM 才能保存在内存中(50000 * 25000 * 4 字节)。如果一台计算机的 RAM 多于另一台计算机,则速度会产生巨大差异,因为它不必经常交换到磁盘。您应该考虑抓取图像的子部分并使用这些部分,而不是整个部分。

    编辑:您使用的是最新的 Java 和图形驱动程序吗?如果你的图片只有 5Kx2.5K,我唯一能想到的就是它没有任何硬件加速。

    【讨论】:

    • 不,我的意思是 5000x2000,我确实发现 50000x20000 的数字相当大,然后意识到我在数字的末尾加上了一个额外的 0,我可能会慢慢失明或其他什么。
    【解决方案5】:

    检查屏幕设置。我敢打赌,这两个系统的像素深度不同,而慢速系统的像素深度与您要显示的图像对象相关。

    【讨论】:

      【解决方案6】:

      由于 Java uses OpenGL to do 2D drawing,您的应用程序的性能将受到相应计算机中图形芯片的 OpenGL 性能的影响。 3D 行业对 OpenGL 的支持正在减少,这意味着(具有讽刺意味的是)新芯片在 OpenGL 渲染方面可能比旧芯片慢 - 不仅是由于硬件,还有驱动程序。

      【讨论】:

        【解决方案7】:

        你试过全屏独占模式吗?

        这可能会有所帮助: http://download.oracle.com/javase/tutorial/extra/fullscreen/index.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-12
          • 2012-08-02
          • 2021-08-07
          • 2014-03-28
          • 1970-01-01
          • 1970-01-01
          • 2019-08-22
          • 1970-01-01
          相关资源
          最近更新 更多