在Java中显示数百万图像的最佳方法是什么?

Miz*_*zur 19 java swing javafx imageview

你看到了吗?

在此输入图像描述

每个房子的每块砖都是16x16像素的图像.

您可以在这里看到一个基于简单JavaFX的版本,其中一些Imageview在X和Y上移动以产生"构造"的效果.

我只是将其改编为Swing使用paintComponent.

问题: - 使用JavaFX:我的电脑有问题.您在图片上看到的内容需要2秒才能加载,然后移动速度非常慢且不稳定.- 使用Swing:我不知道如何根据亮度,阴影等调整每个块.所以它看起来像这样:

在此输入图像描述

我应该选择什么方法?两者都有很大的缺点.我本来希望保留JavaFX方法,但也想找到别的东西Imageview.这应该不是一个好主意.

jew*_*sea 32

有关Swing优化和实现的信息,请参阅其他答案,因为我的答案是JavaFX特定的.

如果你坚持使用JavaFX实现,这里有几件事要尝试:

  1. 使用node.setCache(true)打开节点缓存.
  2. 使用node.setCacheHint(CacheHint.SPEED)启用高速节点转换.
  3. 提供一个没有效果的实现,另一个带有效果的实现,看看没有效果的实现是否明显更好.(如果是这种情况,您可能需要使用更有效的效果链或完全放弃一些效果).
  4. 检查JavaFX系统要求,确保您的设置满足硬件/操作系统/驱动程序组合方面的硬件加速最低要求.
  5. 如果您正在使用基于区域和css的处理,请注意css系统不会导致太多开销(例如,通过使用不使用css并比较其性能的代码版本).
  6. 如果需要,实现一定程度的细节缩放(例如,当缩小时为整个房屋提供单个图像而不是为每个房屋瓷砖提供单独的图像).
  7. 确保您只加载一次给定的图像并在多个ImageView中重复使用它.
  8. 使用分析器识别瓶颈.
  9. 改变测试CPU或显卡,看看其中任何一个是否是瓶颈.
  10. 尝试Java 8预览,其中包含许多针对JavaFX的内部性能优化.
  11. 如果要加载大量图像,请使用背景加载,并在加载图像时在前面播放动画或进度条.
  12. 如果要加载大量图像,请在Image构造函数中预先缩放它们,这样它们就不会占用太多内存或者需要(可能)额外像素的额外处理能力(如果你使用了大量的像素,那么这只是一个考虑因素)不同的非常高分辨率的纹理 - 你似乎没有这样做.

例如:

Image tile = new Image("tile.png");

Group house = new Group();
house.setCache(true);
house.setCacheHint(CacheHint.SPEED);

Effect lighting = new Lighting();

for (int i = 0; i < houseWidth; i++) {
  // here is the critical part => don't do new ImageView(new Image("tile.png"))
  ImageView tileView = new ImageView(tile));
  tileView.setEffect(lighting);
  tileView.setCache(true);
  tileView.setCacheHint(CacheHint.SPEED);

  house.add(tileView);  
}
Run Code Online (Sandbox Code Playgroud)

曼特里德的建议很有意思.我相信,使用JavaFX,您不需要自己实现脏矩形算法(因为底层平台能够为您处理脏区域处理).可能是因为它是一种通用机制,它不提供特定情况所需的优化级别,在这种情况下,您需要自己处理脏处理(例如,从场景图中删除节点并重新添加)他们酌情).

另外,可以通过在JavaFX中定义效果,将效果应用于屏幕外ImageView节点,然后拍摄屏幕外ImageView节点的快照以获得预先计算的图像来预先计算图像上的模糊/亮度等.此技术允许您重用现有的JavaFX效果管道,而无需使用ConvolveOp机制重新实现它.也许你可以通过将cache设置为true并将cacheHint设置为ImageView节点上的速度来获得相同的性能级别,因为我相信这会在场景背后发生类似的事情(即以增加内存使用量为代价提高速度).


JavaFX场景图非常有效,可以处理数千个节点.但是,您的应用程序可能不止这些.如果上述优化点对您没有帮助,您可能需要计算节点数并将问题(可能还有一些来源)的引用发布到open-jfx邮件列表中,其中JavaFX开发人员了解JavaFX应用程序的详细信息优化是.

与JavaFX 2.2中的(通常无用的)3D场景图相比,JavaFX 8对3D场景图形的支持要好得多.您的当前应用程序似乎是psuedo-3d,您可以在其中转换2D对象,单独应用光照效果并调整每个图块的亮度以获得3D外观.如果是这种情况,使用具有统一3D照明模型的全硬件加速3D场景图可能最终表现更好,看起来更好并且更容易使用 - 您必须在应用程序的上下文中评估它以查看它是否是值得将您的应用程序从2D JavaFX场景图切换到3D JavaFX场景图,或从JavaFX切换到Swing或其他一些技术,如libgdx.

附录

回答一些Mizur的其他问题:

那他们为什么这么耗电呢?

从我的回答中可以看出,有许多方面涉及到性能,因此挑出一个特定的原因,为什么某些东西耗电有时是困难的,往往是不可能的.有时它是导致性能问题的组合.最大的胜利通常来自优化内部循环中执行的内容或通过更改用于解决问题的策略.

如果他们需要这么多,请让我移动瓷砖,或者只是显示,不是吗?

就仅消耗你移动的东西的资源而言,JavaFX场景图对此有一些优化,而像cachehints这样的东西可以进一步提高性能.也许它们不足以满足您的特定用例或您使用系统的方式.您可能需要更改算法以减少系统负载.

有没有办法用Imageview技术生成每个建筑物的图像,然后在最终场景中整合这些建筑物的图像?

是 - 您可以使用许多图像和节点将建筑物渲染到屏幕外场景,对屏幕外场景进行快照以创建单个图像,然后将该图像覆盖在最终场景上.