2009-08-02 206 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 = new ImageIcon(image).getImage(); 

得到加載,這樣image.getwidth(空)和image.getHeight(空)返回有效結果的所有像素。

除了增加堆大小之外,還有其他的方法嗎?

+0

多大的圖像?你用Xmx來增加內存嗎?爲什麼不使用ImageIO.read(URL)和朋友來獲取BufferedImage的圖像? – akarnokd 2009-08-02 17:14:17

+0

我很困惑,爲什麼你需要ImageIcon,以及爲什麼你需要用圖形上下文繪製圖像。如果只用`try/catch`塊迭代`images`會發生什麼? – banjollity 2009-08-02 17:15:47

+0

@ kd304 圖像可以是任意大小。我從掃描儀中提取它們。我用來從掃描儀獲取圖像的代碼返回對java.awt.Image對象的引用。 我無法通過向JVM傳遞參數來增加內存,因爲我在applet中執行此操作,而且我不想打擾用戶進行配置。 – 2009-08-02 20:10:28

回答

1

你可以通過不把所有的圖像保存在一個集合中然後迭代來保存一些堆。相反,檢索和寫入每個圖像,你得到它。我建議的代碼中的hasMoreImages()scanner.getNextImage()部分是這樣的一個可能的實現。

我也會質疑用Graphics上下文繪製圖像的智慧,當它可能已經處於可以用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. 
    } 
} 
1

您的問題是圖像掃描儀是巨大 - 以600 dpi,我們談論了100 MB每色A4頁面壓縮。良好的掃描儀可以以數千DPI掃描 - 在2000 DPI時,單個未壓縮的彩色頁面將超過1 GB。高質量掃描的大小會吸引大多數人在第一次開始與他們合作時沒有做好準備。

除非您正在運行帶有演出和演出的RAM的64位操作系統,否則您永遠不會在內存中放入超過幾張圖片。掃描黑色&白色或灰度和較低的分辨率將有所幫助,但最好的解決方案是改變處理圖像的方式。

不要在內存中獲取圖像集合 - 一次獲取每張圖像的,並寫出圖像直至完成。把你的TWAIN驅動程序和API工作 - 讓它通過你的緩衝區與圖像的一部分,直到完成。你可能是關閉使用Java庫更好地做到這一點比滾動自己的圖像處理


編輯:鏈接的Java庫TWAIN