Javaで何百万もの画像を表示する最適な方法は何ですか? 質問する

Javaで何百万もの画像を表示する最適な方法は何ですか? 質問する

見えますか?

ここに画像の説明を入力してください

各家の各レンガは 16 x 16 ピクセルの画像です。

ここで見られるのは、シンプルな JavaFX をベースにしたバージョンで、ImageviewX と Y を移動して「構築」効果を生み出しています。

Swingこれをを使用するように適応させるだけですpaintComponent

問題: - JavaFX の場合: コンピューターに問題があります。画像に表示されているものは、ロードに 2 秒かかり、その後非常に遅くぎくしゃくして動きます。 - の場合Swing: 明るさ、影などに応じて各ブロックを調整する方法がわかりません。そのため、次のようになります。

ここに画像の説明を入力してください

どの方法を選択すればよいでしょうか? どちらにも大きな欠点があります。JavaFX 方式を維持したいのですが、それ以外の方法も見つけたいと思っていますImageview。これは良い考えではないはずです。

ベストアンサー1

Swing の最適化と実装の詳細については、私の回答は JavaFX に固有のものであるため、他の回答を参照してください。

JavaFX 実装に固執する場合は、次のことを試してみてください。

  1. 使用ノードをキャッシュに設定します(true)ノード キャッシュをオンにします。
  2. 使用node.setCacheHint(CacheHint.SPEED)高速ノード変換を可能にします。
  3. エフェクトなしの実装とエフェクトありの実装を用意し、エフェクトなしの実装の方がパフォーマンスが著しく優れているかどうかを確認します。(その場合、より効率的なエフェクト チェーンを使用するか、一部のエフェクトを完全に使用しなくなる可能性があります)。
  4. チェックしてくださいJavaFX システム要件ハードウェア/OS/ドライバーの組み合わせに関して、セットアップがハードウェア アクセラレーションの最小要件を満たしていることを確認します。
  5. 使用している場合地域CSSベースの処理では、CSSシステムあまりオーバーヘッドが発生していないこと (たとえば、CSS を使用しないコード バージョンを用意して、そのパフォーマンスを比較するなど)。
  6. 必要に応じて、詳細レベルのズームを実装します (たとえば、ズームアウトしたときに、各家のタイルごとに個別の画像ではなく、家全体の単一の画像を提供します)。
  7. 指定されたものだけをロードしていることを確認してください画像一度使って複数回再利用する画像ビュー
  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);  
}

Mantrid の提案は興味深いです。JavaFX では、ダーティ レクタングル アルゴリズムを自分で実装する必要はないと私は信じています (基盤となるプラットフォームがダーティ領域の処理を行えるため)。これは汎用的なメカニズムであるため、特定のケースに必要なレベルの最適化が提供されない可能性があり、その場合はダーティ処理を自分で処理する必要があります (たとえば、シーングラフからノードを削除し、必要に応じて再度追加するなど)。

さらに、画像のぼかしや明るさなどを事前に計算するには、JavaFXでエフェクトを定義し、そのエフェクトをオフスクリーンのImageViewノードに適用し、スナップショットを撮るオフスクリーンの ImageView ノードを使用して、事前に計算された画像を取得します。この手法を使用すると、ConvolveOp メカニズムを使用して再実装する必要なく、既存の JavaFX エフェクト パイプラインを再利用できます。ImageView ノードで cache を true に設定し、cacheHint を speed に設定するだけで、同じパフォーマンス レベルが得られる可能性があります。これは、舞台裏で同様のこと (つまり、メモリ使用量の増加を犠牲にして速度を向上させる) を行うためだと考えられます。


JavaFXシーングラフは非常に効率的で、数千のノードを処理できます。ただし、アプリケーションにはそれ以上のノードがある可能性があります。上記の最適化ポイントが役に立たない場合は、ノード数を計算し、質問への参照(およびソース)を投稿することをお勧めします。open-jfx メーリング リストJavaFX アプリケーションの最適化の詳細を熟知した JavaFX 開発者がいます。

JavaFX 8では、3DシーングラフJavaFX 2.2の(ほとんど役に立たない)3Dシーングラフよりも優れています。現在のアプリケーションは、2Dオブジェクトを変換し、個別に照明効果を適用し、各タイルの明るさを調整して3Dの外観を実現する疑似3Dのようです。その場合、統合された3D照明モデルを備えた完全にハードウェアアクセラレーションされた3Dシーングラフを使用します。5月最終的にはパフォーマンスが向上し、見た目も良くなり、作業が簡単になります。2D JavaFXシーングラフから3D JavaFXシーングラフに、またはJavaFXからSwingやその他の技術に切り替える価値があるかどうかを判断するには、アプリケーションのコンテキストで評価する必要があります。libgdx

補遺

Mizur の追加の質問に対する回答:

では、なぜそれほど電力を消費するのでしょうか?

私の回答からわかるように、パフォーマンスにはさまざまな側面が関係しているため、何かが電力を消費する理由を 1 つだけ特定することは難しい場合があり、不可能な場合もよくあります。パフォーマンスの問題に寄与する要因が複数ある場合もあります。通常、最も大きな効果は、最も内側のループで実行されるものを最適化するか、問題を解決するために使用する戦略を変更することで得られます。

そんなに必要ならば、タイルを移動させたり、そのまま表示させたりしてください。

移動するものに対してのみリソースを消費するという点では、JavaFX シーングラフにはそのための最適化がいくつかあり、キャッシュヒントなどによってパフォーマンスをさらに向上させることができます。おそらく、それらは特定のユースケースやシステムの使用方法には十分ではないでしょう。システム負荷を軽減するには、アルゴリズムを変更する必要があるかもしれません。

Imageview のこの技術を使用して各建物の画像を生成し、それらの建物の画像を最終シーンに統合する方法はありますか?

はい、多くの画像とノードを使用して、建物をオフスクリーンシーンにレンダリングできます。オフスクリーンのシーンをスナップショットする単一の画像を作成し、その画像を最終シーンに重ねます。

おすすめ記事