2015-01-27 117 views
0

我有一個要求使用讀取一些專有圖像文件格式(有關不重新發明我們自己的車輪)的本機庫。圖書館工作正常,只是有時圖像可以變得非常大(我見過的記錄是13k x 15k像素)。問題是我可憐的JVM一直在痛苦的死亡和/或拋出OutOfMemoryError的任何時候圖像開始變得巨大。將原始像素數據(作爲字節數組)轉換爲BufferedImage

這裏是我已經運行

//the bands, width, and height fields are set in the native code 
//And the rawBytes array is also populated in the native code. 

public BufferedImage getImage(){ 
    int type = bands == 1 ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_INT_BRG; 
    BufferedImage bi = new BufferedImage(width, height, type); 
    ImageFilter filter = new RGBImageFilter(){ 
     @Override 
     public int filterRGB(int x, int y, int rgb){ 
      int r, g, b; 
      if (bands == 3) { 
       r = (((int) rawBytes[y * (width/bands) * 3 + x * 3 + 2]) & 0xFF) << 16; 
       g = (((int) rawBytes[y * (width/bands) * 3 + x * 3 + 1]) & 0xFF) << 8; 
       b = (((int) rawBytes[y * (width/bands) * 3 + x * 3 + 0]) & 0xFF); 
      } else { 
       b = (((int) rawBytes[y * width + x]) & 0xFF); 
       g = b << 8; 
       r = b << 16; 
      } 
      return 0xFF000000 | r | g | b; 
     } 
    }; 

    //this is the problematic block 
    ImageProducer ip = new FilteredImageSource(bi.getSource(), filter); 
    Image i = Toolkit.getDefaultToolkit().createImage(ip); 
    Graphics g = bi.createGraphics(); 
    //with this next line being where the error tends to occur. 
    g.drawImage(i, 0, 0, null); 
    return bi; 
} 

這段代碼的偉大工程,對於大多數圖像,只要他們不是骯髒的大。它的速度也很好。問題在於,Image畫到BufferedImage的步驟吞下太多內存。

有沒有一種方法可以跳過這一步,直接從原始字節到緩衝圖像?

回答

2

使用jai的RawImageInputStream。這確實需要了解有關SampleModel的信息,這些信息似乎來自本機代碼。

另一種選擇是將您的rawBytes放入DataBuffer,然後create a WritableRaster,最後創建一個BufferedImage。 這實質上就是RawImageInputStream的功能。

+0

由於內存使用似乎是這裏的問題,後面的選項可能是最好的,因爲你可以直接從原始字節數組(即'new DataBufferByte(rawBytes,rawBytes.length)'')創建'DataBuffer') 。 – haraldK 2015-01-27 08:53:29

+0

美麗的事情,男性。精彩的工作。 – captainroxors 2015-01-27 17:48:25