2016-09-23 76 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不立即回收內存,它在需要時會這樣做。其次,'BufferedImage'的'flush()'不釋放像素數據(它只刷新「表面數據」,這可能是視頻RAM中JVM堆外部的高速緩存表示)。你的'i'變量引用的'BufferedImage'在循環的每次迭代之後*都可用於GC *,但它可能不會立即發生。 – haraldK

+0

...或換句話說,這裏沒有什麼錯...... :-) – haraldK

+0

好的 - 謝謝。我認爲它很好奇......我在一個tomcat web應用程序中使用直方圖代碼,該代碼可以從一個循環中的超過10,000個圖像中提取直方圖。在那裏內存增加非常迅速(我沒有在這段時間保存直方圖,但tomcat需要超過10GB的內存o.o)。如果我在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 ; 
} 

要小心,有些彩色圖像也有一個alpha通道,這意味着pixelLength將是4,而不是3

當你完成它時,你是否清空(刷新)直方圖?因爲有1600萬組合/三色的顏色。

+0

謝謝!是的,我完成後,我正在使用histogram.clear() –