java - 使用 JAI 在 Java 中使用 TIFF 渲染提高性能

标签 java tiff jai

我一直在研究分析显微镜数据的软件,这些数据存储为多层 tiff 文件。在浏览了 StackOverflow 和 JAI 文档之后,我拼凑了一些代码来存储 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

请注意在拖动 slider 时帧偶尔会出现断断续续的情况。

我通过在缩放时删除平滑来提高图像放大时的性能,但它仍然没有我想要的那么快。

我的代码如下:

/** 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();
}

我已经使用 JAI 将多层 tiff 加载到 imageDecoder 中,并在拖动 slider 时显示正确的层,我使用以下代码:

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;}

基本上,每当拖动 slider 时,我都会从 imageStack 中提取渲染图像,将其转换为 BufferedImage(以便它可以与 ImageIcon 一起使用),对其进行缩放,并将其设置为显示图像。我认为较慢的部分是将其转换为缓冲图像并对其进行缩放。有什么方法可以更快地做到这一点?

有没有人对如何改进有任何建议,或者从类似的经历中获得见解?

如有任何帮助,我们将不胜感激。

最佳答案

我遇到了完全相同的问题并最终使用 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)。

关于java - 使用 JAI 在 Java 中使用 TIFF 渲染提高性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8395456/

相关文章:

java - "during the operation of the Java Virtual Machine"的定义是什么?

jai - jpedal jpg2000 错误

Java JAI BufferedImage 与 C++ OpenCV Mat imread?

java - JAI:读取 12 位 JPEG 文件

java - 使用 MEME 图像等文本创建图像并保存为图像文件。使用 Canvas 在位图上绘制时无法保存图像

java - Maven 发布更新策略

java泛型类型参数和这些类型的操作

java - 将 PDF 转换为多页 tiff(第 4 组)

c# - 将字节数组 Tiff 转换为字节数组 Jpeg

c# - 将 TIFF 转换为 JPG 格式