2009-07-13 26 views
4

Javaで大きな画像ファイルを読み込もうとしていますが、ファイルが大きすぎるとメモリエラーメッセージが表示されています(既にコマンドラインフラグでヒープサイズを増やしてみました)。Javaで大きな画像を読み込む方法

BufferedImage img = ImageIO.read(fileToOpen); 

、ファイルがTIFFの場合は、私はこのコードを使用しています:イメージは、私はこのコードを使用していたTIFF画像ではない場合

私は、以下の方法で画像をロードしています:

BufferedImage img = JAI.create("fileload", 
    fileToOpen.getAbsolutePath()).getAsBufferedImage(); 

私の質問は、実際にはこれに沸く:どのようにメモリエラーを取得せずに(例えば、Photoshopのような)画像操作プログラム数百メガバイトのロードファイル?

20MBのJPEGをメモリに読み込むのが難しい理由は、BufferedImageに読み込むと、イメージを非圧縮形式で保存するなどの理由からです。したがって、可能な解決策の1つは、Imageクラスをサブクラス化して圧縮された形式でデータを格納するJavaクラスを持つことです。しかし、それはおそらくランタイムマシンが描画中にデータを解凍する必要があるため、スピードの問題があります。もう1つの選択肢は、圧縮されていない生データをディスクにキャッシュし、そこからシームレスに読み取ることですが、速度の問題は引き続き発生します。

大男たちはどうやってそれをしますか? Photoshopはどのようにメモリに200MBのJPEGをロードし、明らかな問題を起こさずに解像度をすべて引き出すことができますか?

(最後の注意:私のアプリケーションであるためスピードの問題の私は私のBufferedImageを取得した後、私は同じ寸法を持つVolatileImageにその内容を描く。これは、大幅に描画速度を向上させる)

答えて

5

非圧縮RGBAイメージに必要なメモリwidth * height * 4バイトです。これに従ってメモリを設定してみてください。基礎となるJDK/DirectX /などのサイズ制限がある可能性があります。しかしシステム。

大きな男の子はJPG画像の構造を利用し、メモリに読み込む必要はありません。おそらく、毎回ファイルから直接それを描画します。

BufferedImageには、揮発性イメージと同様の自動アクセラレーション機能があります。アクセラレーションの優先度を1に設定すると、最初のペイントは最新のJDKでVRAMに移動します。

あなたは32ビットシステムを実行しているとします。圧縮されていないイメージが1.4GBを超える非常に大きい場合、JVMの制限によりメモリ内でそれを処理することはできません。イメージがワンタイムイメージでない場合、一時的なイメージにストリームを解凍し、ランダムなファイルアクセスを使用してその一部を取得するツールを見つけることができます。

+0

ありがとうございました。特に設定された加速部分。誰かがより適切な(私の場合)の回答が出てくる場合は、正しい投票ボタンを予約しています –

+0

あなたは答えを受け入れることを意味します。有益な回答を投票するのは無料で、SOの限度額ですでに投票がなくなっていない限り、すべての回答についてそれを行うことができ、予約する必要はありません。質問を洗練させるオプションもあります。おそらく私(または他の誰か)がより正確な答えを出すことができます。 – akarnokd

+0

heheはい私はそれを意味しました。私も投票ボタンを意味した。私は答えが未回答のセクションに残って、より多くの露出のためにもう少し長くしてから投票することを望みます。私はあまりにも非倫理的ではないことを願っています:P –

3

トリックはフルサイズの画像を扱っていません。これを現在の解像度の50×50ピクセルのような扱いやすい部分に分割し、必要に応じて元のファイルからコンテンツを生成します。所与の部分が必要でない場合(例えば、画面外にある場合)、それは削除することができ(弱い参照は完全である)、またはディスクに永続化することができる。

+0

しかし、もう一度:作品を生成するために、私はメモリに少なくとも一度画像をロードする必要はありませんか? –

+0

である必要はありません。注意深く細工されたイメージデコーダは、問題のピースの領域をデコードするために必要なバイトだけを読み取ることができます。 –

0

解決策は、BigBufferedImageです。これは、メモリの制限よりもはるかに大きな画像をロードして保存することができます。そのトリックは、バッファがDataBufferのファイルベースの実装に置き換えられていることです。イメージはハードドライブに保存されます。 RAMは使用されません。これにより、OutOfMemoryExceptionを防ぐことができます。

イメージファイルからBigBufferedImageを作成します:read this articleを扱う大きな画像の詳細については

BigBufferedImage image = BigBufferedImage.create(
     tempDir, width, height, TYPE_INT_RGB); 

:空BigBufferedImageを作成

BigBufferedImage image = BigBufferedImage.create(
     inputFile, tempDir, TYPE_INT_RGB); 

関連する問題