我一直在研究分析显微镜数据的软件,这些数据存储为多层 tiff 文件。在查看了 StackOverflow 和 JAI 文档之后,我拼凑了一些代码来存储 tiff 堆栈并正确呈现它。
但是,它的性能很差。在阅读了这样的帖子后,我曾希望能获得更快的性能: 任何人都有用 Java 编写一个非常快速的 tiff 查看器/编辑器的运气吗?
不幸的是,它并没有我希望的那么好。我在使用外部图像库或 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();
}
我已经使用 JAI 将多层 tiff 加载到 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 一起使用),对其进行缩放,并将其设置为显示的图像。我认为缓慢的部分是将其转换为缓冲图像,并对其进行缩放。有什么办法可以更快地做到这一点?
有没有人对如何改进事情有任何建议,或者从类似的经历中获得洞察力?
任何帮助将非常感激。