2009-08-02 30 views
1

いくつかのjava.awt.Imageオブジェクトをディスクに保存します。しかし、私が好きだとしようとするとき:BufferedImageとImageIOを使用して画像を保存するときにメモリ不足の問題が発生する

for (Image image : images) { 
    image = new ImageIcon(image).getImage(); 
    BufferedImage temp = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); 
    Graphics2D g = temp.createGraphics(); 
    g.drawImage(image, 0, 0, null); 
    g.dispose(); 
    File tempFile = null; 
    try { 
     tempFile = File.createTempFile("img", ".jpg"); 
     ImageIO.write(temp, "jpg", tempFile); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    files.add(tempFile); 
} 

私はJavaヒープスペースエラーを取得します。

私はimage.getwidth(ヌル)とimage.getHeight(ヌル)が、有効な結果を返すように、すべてのピクセルがロードされて得るために

image = new ImageIcon(image).getImage(); 

を配置する必要がありました。

ヒープサイズを増やす場合を除いてこれ以外の方法はありますか?

+0

イメージでどのように大:あなたはおそらく


編集を扱う独自のイメージを転がりよりもこれを行うにはJavaライブラリを使用して方がいいでしょう? Xmxを使ってメモリを増やしますか?なぜImageIO.read(URL)や友達を使ってBufferedImageとして画像を取得しないのですか? – akarnokd

+0

ImageIconが必要な理由と、なぜGraphicsコンテキストでイメージをペイントする必要があるのか​​、混乱しています。 'try/catch'ブロックだけで' images'を反復するとどうなりますか? – banjollity

+0

@ kd304 画像のサイズは自由です。私はスキャナからそれらを取得しています。スキャナから画像を取得するために使用するコードは、java.awt.Imageオブジェクトへの参照を返します。 パラメータをJVMに渡すことでメモリを増やすことはできません。なぜなら、私はアプレットでそれをやっているので、ユーザーは設定を邪魔したくないからです。 –

答えて

1

コレクション内のすべてのイメージを保持しないで、ヒープを保存し、次にそれを繰り返すことができます。代わりに、取得した各イメージを取得して書き出します。私の提案したコードのhasMoreImages()scanner.getNextImage()部分は、これを実装する可能性があります。

ImageIOを使って書くことができる状態になっているときに、グラフィックスコンテキストでイメージを描くことの賢明さに疑問を持ちます。 ImageIO.write()にはRenderedImageが必要です。そのため、インスタンスの迅速なチェックで十分です。

while(hasMoreImages()) { 
    Image image = scanner.getNextImage(); 

    if (image instanceof RenderedImage)) { 
     File tempFile = File.createTempFile("img", ".jpg"); 
     ImageIO.write((RenderedImage)image, "jpg", tempFile); 
     files.add(tempFile); 
    } else { 
     // Do your ImageIcon code thing here. 
    } 
} 
+0

My ImageはRenderedImageではありません。 MemoryImageSourceによって作成されたImageで、Javaコードの外側にDLLで埋められています。私はちょうどそのDLLの関数を呼び出すことによってImagesのコレクションを取得します。 ImageとMemoryImageSourceのメモリ割り当てはDLLで行われ、ヒープスペースには影響しません。しかし、私がJavaコードの中から画像を保存したいときは、BufferedImagesをImagesから外してヒープをいっぱいにする必要があったと思います。 –

+0

新しいjava.awt.image.DataBufferを実装し、カスタムのBufferedImageを作成しようと考えていました。それはうまくいくのだろうか? –

1

あなたの問題は、スキャナ画像が巨大であるということです - 600 dpiで、我々はカラーA4ページごとに圧縮されていない100 MB以上を話しています。優れたスキャナーは何千ものDPIでスキャンできます.2000 DPIでは、1つの非圧縮カラーページが1 GB以上になります。良質のスキャンのサイズは、最初に作業を始めるときに準備ができていないほとんどの人を捉えます。

gigsとgigsのRAMを搭載した64ビットオペレーティングシステムを実行しているのでなければ、メモリ内にいくつかのイメージ以上を収めることは決してありません。 &白またはグレースケールの黒でスキャンすると解像度が低くなりますが、画像を扱う方法を変更するのが最善の解決策です。

メモリ内の画像のコレクションを取得しないでください - 一度に各画像のピースを取得し、完了するまで画像を書き出してください。あなたのTWAINドライバとAPIを動作させる - 完了するまで画像の一部をバッファに渡す。 JavaのTWAINライブラリのリンク

+0

私のためにこれを行うことができるライブラリを知っていますか? –

+0

あなたの特定のDLLと接続について十分にはわかりません - もっと情報が役立つでしょう。 TWAINドライバから直接取得してディスクに書き込むだけのソフトウェアがたくさんあることに注意してください。どのスキャナーにも少なくとも1つは付属しており、私は3頭も頭の上に置くことができます。 – BobMcGee

+0

上記のように、TWAINドライバから直接ディスクに画像を取得し、後で必要に応じてアクセスしてください。アプレットは、ローカルファイルシステムにアクセスするためのアクセス許可を得るために署名する必要があります。回答を受け入れることで、この問題が解決し、SOの先頭ページに自動的に表示されなくなります。 –

関連する問題