2016-09-23 7 views
0

複数の画像からヒストグラムを作成したい。 このプロセスを実行するには、DataBufferByte にアクセスします。ヒストグラムを作成した後にGCがメモリを解放しないことを認識しました。 このコードで何が問題になっていますか?ご支援のためのBufferedImageのピクセルアクセス - メモリリーク?

import java.awt.Color; 
import java.awt.image.BufferedImage; 
import java.awt.image.DataBufferByte; 
import java.io.File; 
import java.io.IOException; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map.Entry; 
import java.util.concurrent.atomic.AtomicInteger; 
import javax.imageio.ImageIO; 


public class Histogram { 

    HashMap<Color,AtomicInteger> histogram; 

    public Histogram() { 
     histogram = new HashMap<>(); 
    } 

    public void build(BufferedImage image){ 

     int pixelLength = 3; 

     byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); 

     int red, green, blue; 
     Color color; 
     for (int pixel = 0; pixel <= pixels.length - pixelLength; pixel+= pixelLength) { 

      blue= ((int) pixels[pixel] & 0xff); // blue 
      green= (((int) pixels[pixel + 1] & 0xff)); // green 
      red = (((int) pixels[pixel + 2] & 0xff)); // red 
      color = new Color(red, green, blue); 
      if(histogram.containsKey(color)){ 
       histogram.get(color).incrementAndGet(); 
      } 
      else{ 
       histogram.put(color, new AtomicInteger(1)); 
      } 
     } 
     pixels = null;  
    } 

    public static void main(String[] args) { 
     String pathImage = "C://testjpg"; 
     try { 
      for (int j = 0; j < 5000; j++) { 
       BufferedImage i = ImageIO.read(new File(pathImage)); 

       Histogram h = new Histogram(); 

       h.build(i); 
       i.flush(); 

      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     }  
    } 
} 

感謝:)

+0

まず、GCはメモリをただちに回収しません。第2に、 'BufferedImage'の' flush() 'はピクセルデータを解放しません(ビデオRAMのキャッシュされた表現である"​​表面データ "のみをフラッシュします)。あなたの 'i'変数で参照される' BufferedImage'は、あなたのループの各繰り返しの後にGC *で利用可能ですが、すぐには発生しないかもしれません。 – haraldK

+0

...言い換えれば、ここに何も間違っていません... :-) – haraldK

+0

大丈夫です - ありがとうございます。私は非常に興味があると思う...私はヒストグラムコードをTomcat Webアプリケーションで使用し、ループ内の10,000以上の画像からヒストグラムを抽出します。そこではメモリが非常に急速に増加します(私はこの時点でヒストグラムを保存しませんが、Tomcatは10GB以上のRAMを必要とします)。 Windowsマシンでスタンドアロンのプログラムを実行すると、うまく見えます... –

答えて

1

は、GCが自動的に実行し、それを必要とする場合にのみ、メモリーをリコールしません。 System.gc()を使用して強制することもできますが、あまり頻繁に実行しないように注意してください。そうしないとプログラムが遅くなります。

あなたのコードが正常に動作し、ここで私がテストしてみたものです:

public static void buildColorHistogram(BufferedImage image) 
{ 
final int pixelLength = 3; 

byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); 

for (int pixel=0 ; pixel < pixels.length; pixel+=pixelLength) 
    { 
    final int blue = pixels[pixel] & 0xff ; // blue 
    final int green= pixels[pixel + 1] & 0xff ; // green 
    final int red = pixels[pixel + 2] & 0xff ; // red 
    Color color = new Color(red, green, blue) ; 
     if (histogram.containsKey(color)) 
      histogram.get(color).incrementAndGet() ; 
     else 
      histogram.put(color, new AtomicInteger(1)) ; 
    } 

pixels = null ; 
} 

pixelLengthは4ではなく3

になることを意味し、いくつかのカラー画像もアルファチャンネルを持っていることに注意してください

完了したらヒストグラムを空にしますか(フラッシュ)しますか?なぜなら、1600万の組み合わせ/三つ組の色があるからです。

+0

ありがとう!はい、私はhistogram.clear()を鍛造しています。 –

関連する問題