2009-07-13 94 views
4

我正嘗試在Java中加載大圖像文件,如果文件太大(我已經嘗試通過命令行標記增加堆大小),我正在收到內存錯誤消息。如何在Java中加載大圖像

我加載與以下方式圖片:

如果圖像是不是我用這個代碼TIFF圖像:

BufferedImage img = ImageIO.read(fileToOpen); 

如果該文件是一個TIFF我使用這個代碼:

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

我的問題實際上歸結爲:圖像處理程序(如Photoshop)如何加載數百兆字節的文件而不會出現內存錯誤?

這是我的理解,20MB jpeg難以加載到內存中的原因是,因爲當加載到BufferedImage例如您保存圖像以未壓縮的方式。所以一個可能的解決方案是擁有一個Java類,該類繼承了Image抽象類的子類,但將數據存儲爲壓縮格式。但是這可能會帶來速度問題,因爲運行時機器在繪圖時不得不解壓縮數據。另一種選擇是將未壓縮的原始數據緩存到磁盤並從中無縫讀取,但速度問題仍然存在。

那麼大男孩們怎麼做呢? Photoshop如何在內存中加載200MB jpeg並繪製所有分辨率而不會出現任何明顯問題?

(最後提示:在我因爲速度問題的應用程序後,我讓我的BufferedImage我畫的內容到具有相同尺寸的VolatileImage這增加了拉絲速度大大)

回答

5

未壓縮RGBA圖像所需的內存是寬*高* 4字節。嘗試根據此設置你的記憶。底層JDK/DirectX /等可能會有大小限制。系統。

大男孩利用JPG圖像的結構,他們不需要將其加載到內存中。也許他們每次都直接從文件中提取它。

BufferedImage具有類似於易失性圖像的自動加速功能。將加速優先級設置爲1,第一個繪圖將在最新的JDK上將其移至VRAM。

編輯我假設你正在運行一個32位系統。如果您的未壓縮映像很大,超過1.4GB,由於JVM限制,您將無法在內存中處理它。如果圖像不是一次性圖像,那麼您可以找到工具將其解壓縮爲臨時原始圖像,並使用隨機文件訪問來抓取部分圖像。

+0

謝謝你的回答。尤其是設定的加速度部分。我保留正確的投票按鈕,以防有人提出更適用的(對我的情況)回答 – 2009-07-13 14:11:45

+0

您的意思是接受答案。投票贊成有用的答案是免費的,您可以爲每個答案做到這一點,不需要保留答案,除非您已經因爲限額而用完選票。您也可以選擇優化您的問題,也許我(或其他人)可以提出更準確的答案。 – akarnokd 2009-07-13 14:16:17

3

訣竅是不處理全尺寸的圖像。將其分爲可管理的片段,例如當前分辨率的50 x 50像素,並在需要時從原始文件生成內容。如果不需要給定片段(例如,關閉屏幕),則可以將其刪除(弱參考將是完美的)或者持續到磁盤。

0

解決方案是BigBufferedImage。它可以加載和存儲比內存限制大得多的圖像。訣竅是它的緩衝區被替換爲基於文件的DataBuffer實現。它將圖像存儲在硬盤上。沒有使用RAM。這可以防止OutOfMemoryException。

從圖像文件創建一個BigBufferedImage:

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

創建一個空BigBufferedImage:

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

有關大圖像處理read this article更多信息。