2011-07-15 63 views
3

我已經問過一個問題如何保存大圖像,我想我在正確的軌道上,但我仍然需要一些建議。保存大圖像 - 光柵問題

我有一個形象的12000條12000,我需要將其保存爲png格式

BufferedImage中不能使用。

我已經建議使用RenderedImage接口,但不知何故我無法得到所需的結果。 (我還沒有與柵格的工作又那麼可能我有什麼不對),用於保存圖像的方法

代碼:爲PanelImage類

public static void SavePanel() { 

    PanelImage IMAGE = new PanelImage(panel); 

    try { 
     ImageIO.write(IMAGE, "png", new File(ProjectNameTxt.getText() + ".png")); 
    } catch (IOException e) { 
    } 

    } 

和代碼:

public static class PanelImage implements RenderedImage { 

    // some variables here 

    public PanelImage(JImagePanel panel) { 
     this.panel = panel; 
    } 

    public Raster getData(Rectangle rect) { 

     sizex = (int) rect.getWidth(); 
     sizey += (int) rect.getHeight(); 
     image = null; 
     image = new BufferedImage(
       (int) sizex, 
       (int) sizey, 
       BufferedImage.TYPE_INT_RGB); 
     g2 = image.createGraphics(); 
     panel.paintComponent(g2); 
     return image.getData(); 
    } 

// rest of the implemented methods - no problems here 
} 

我注意到ImageIO一次請求一行像素(12000 x 1)。 此方法正在工作,但我仍然需要BufferedImage中的整個圖像。 我必須增加每次ImageIO的調用該方法的BImage的大小,否則我得到「座標出界!」 exeption

感謝

+0

首先你說'BufferedImage'不能使用,但是在下面的代碼中你仍然在使用它。所以你是什麼意思?當你嘗試使用'BufferedImage'時,你會得到錯誤信息(也許是'OutOfMemoryError'?)?什麼是確切的錯誤信息? – Jesper

+0

是的,首先我使用了緩衝圖像,但尺寸太大。我被建議只使用緩衝圖像來獲取ImageIO請求的光柵部分,但我不知道該怎麼做 – Icki

回答

3

PNGJ庫可寫巨大的圖像有用的信息/,因爲它是按順序執行的,它一次只在內存中保留一行。 (我自己寫的前一陣子,因爲我也有類似的需求)

+0

非常感謝!我不得不弄清楚如何從我的圖像面板獲取像素,但是我的工作得很好(稍微緩慢地直接保存BufferedImage,但圖像大小不再是問題)。我可以寫一篇教程如何使用你的圖書館來保存這樣的大圖片嗎? – Icki

+0

@lcki:當然。你可以自己添加一個wiki頁面,或者發送給我文本 – leonbloy

2

我只是一個黑客最小工作示例爲ComponentImage,這需要一個任意JComponent並且可以傳遞給ImageIO寫作。爲了簡潔,只有「有趣」的部分包括在內:

public final class ComponentImage implements RenderedImage {  
    private final JComponent comp; 
    private final ColorModel colorModel; 
    private final SampleModel sampleModel; 

    public ComponentImage(JComponent comp) { 
     this.comp = comp; 
      this.colorModel = comp.getColorModel(); 
     this.sampleModel = this.colorModel.createCompatibleWritableRaster(1, 1). 
       getSampleModel(); 
    } 
    @Override 
    public ColorModel getColorModel() { 
     return this.comp.getColorModel(); 
    } 

    @Override 
    public SampleModel getSampleModel() { 
     return this.sampleModel; 
    } 
    @Override 
    public Raster getData(Rectangle rect) { 
     final WritableRaster raster = this.colorModel. 
       createCompatibleWritableRaster(rect.width, rect.height); 

     final Raster result = raster. 
       createChild(0, 0, rect.width, rect.height, 
       rect.x, rect.y, null); 

     final BufferedImage img = new BufferedImage(
       colorModel, raster, true, null); 

     final Graphics2D g2d = img.createGraphics(); 
     g2d.translate(-rect.x, -rect.y); 
     this.comp.paintAll(g2d); 
     g2d.dispose(); 

     return result; 

    } 
} 
+0

我會試試看。我得到了它與這裏提到的PNGJ庫的工作,但也許你的方法會更快。感謝您的幫助 ! – Icki

0

可以使用BigBufferedImage代替的BufferedImage。它可以處理內存限制允許的更大的圖像。訣竅是它的緩衝區被替換爲基於文件的DataBuffer實現。它將圖像存儲在硬盤上,不使用RAM。

從圖像文件創建BigBufferedImage:

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

創建一個空BigBufferedImage:

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

渲染的圖像的一部分:

part = image.getSubimage(x, y, width, height); 

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