2011-12-06 47 views
3

我一直在研究分析顯微鏡數據的軟件,該軟件存儲爲多層tiff文件。在通過StackOverflow和JAI文檔查看之後,我將一些代碼放在一起以存儲tiff堆棧並正確呈現它。使用JAI在Java中進行TIFF渲染可獲得更快的性能

但是,它遭受了一些相當不好的表現。我曾希望看到這樣的帖子後有一些更快的表現: Anyone have any luck writing a very fast tiff viewer/editor in Java?

不幸的是,它不像我希望的那麼好。我沒有太多與外部圖像庫或Java圖形功能有關的經驗,所以我不確定我會如何改進這一點。

對於某些方面,這裏是「口吃」的視頻,同時通過TIFF堆穿越我的經驗: http://www.youtube.com/watch?v=WiR4o6TsqyM&feature=channel_video_title

注意幀偶爾口吃如何隨着滑塊拖動。

當縮放圖像時,通過移除平滑來縮放圖像,但改善後的性能仍然不如我喜歡的那麼快。

我的代碼是下面:

/** Converts the RenderedImage into a BufferedImage, which is more flexible 
* @param img The original RenderedImage 
* @return The new BufferedImage 
*/ 
public BufferedImage convertRenderedImage(RenderedImage img) { 
    if (img instanceof BufferedImage) { 
     return (BufferedImage)img; 
    } 
    ColorModel cm = img.getColorModel(); 
    int width = img.getWidth(); 
    int height = img.getHeight(); 
    WritableRaster raster = cm.createCompatibleWritableRaster(width, height); 
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 
    Hashtable<String, Object> properties = new Hashtable<String, Object>(); 
    String[] keys = img.getPropertyNames(); 
    if (keys!=null) { 
     for (int i = 0; i < keys.length; i++) { 
      properties.put(keys[i], img.getProperty(keys[i])); 
     } 
    } 
    BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); 
    img.copyData(raster); 
    return result; 
} 

/** Draws everything on top of the scaled image 
* @param scale The current scale value 
*/ 
private void setScaledImage(double scale) 
{ 
    //Optimizes the image type for drawing onto the screen 
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
    GraphicsDevice device = env.getDefaultScreenDevice(); 
    GraphicsConfiguration config = device.getDefaultConfiguration(); 

    int w = (int)(scale*currImage.getWidth()); 
    int h = (int)(scale*currImage.getHeight()); 
    scaled = config.createCompatibleImage(w, h, BufferedImage.TYPE_INT_RGB); 
    Graphics2D g2 = scaled.createGraphics(); 
    g2.drawImage(currImage, 0, 0, w, h, null); 
    g2.dispose(); 
} 

我已經加載多層TIFF與JAI一個imageDecoder,並以顯示正確的層滑塊被拖動時,我使用以下代碼:

try { 
    currImage = convertRenderedImage(imageStack.decodeAsRenderedImage(currentLayerSlider.getValue()-1)); 
    setScaledImage (scaleSlider.getValue()/100.0); 
    curves.changeFrame(currentLayerSlider.getValue()); 
    drawImageOverlay();} 
catch (IOException e) { 
    e.printStackTrace(); 
    currImage = null;} 

基本上,無論何時拖動滑塊,我都會從imageStack中提取渲染圖像,將其轉換爲BufferedImage(以便它可以與ImageIcon一起使用),縮放它並將其設置爲顯示的圖像。我認爲緩慢的部分是將其轉換爲緩衝圖像,並將其縮放。有什麼辦法可以更快地做到這一點?

有沒有人有任何建議如何改善事情,或從類似的經驗見識?

任何幫助將不勝感激。

回答

0

而不是使用JLabel的BufferedImage和ImageIcon,你嘗試過使用DisplayJAI嗎? 它可以直接顯示RenderedImage。

3

我遇到了相同問題,結束了使用decodeAsRaster()傳遞給一個轉換方法:

public static BufferedImage convertRenderedImage(Raster raster) { 
    int w = raster.getWidth(); 
    int h = raster.getHeight(); 
    BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
    int[] sourcePixels = ((DataBufferInt)raster.getDataBuffer()).getData(); 
    int[] destPixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData(); 
    System.arraycopy(pixels, 0, rasterData, 0, pixels.length); // The speed-up! 
    return image; 
} 

然後更改您的代碼:

currImage = convertRenderedImage(imageStack.decodeAsRaster(currentLayerSlider.getValue()-1)); 

的速度提高信貸將返回給@Brent Nash here:我們基本上從原始Raster中獲取像素陣列,併爲BufferedImage獲取像素陣列以填充並執行System.arraycopy而不是「昂貴」的image.setData(raster)這是更便攜的,但是,對於每個像素,調用一些方法來檢查一致性和類型,而我們已經擁有了所有我們需要的信息。

該代碼應該是有效的BufferedImage.TYPE_INT_RGB,但我必須承認,我無法測試,但我知道它的工作對BufferedImage.TYPE_BYTE_GRAY(和byte[]/DataBufferByte)。

0

您可以改變你的形象renderd緩衝,然後以J標籤顯示,因爲renderd圖像JAI圖像和j標籤採取onley緩衝圖像,也不要試圖在JAI顯示它您嘗試在一個JLabel