3

私は、多層 tiff ファイルとして保存されている顕微鏡データを分析するソフトウェアに取り組んできました。StackOverflow と JAI ドキュメントに目を通した後、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();
}

マルチレイヤー 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 で使用できるように)、スケーリングして、表示イメージとして設定します。遅い部分は、バッファリングされた画像に変換してスケーリングしていると思います。これをより速く行う方法はありますか?

物事を改善する方法についての提案や、同様の経験からの洞察はありますか?

どんな助けでも大歓迎です。

4

4 に答える 4

3

私はまったく同じ問題に遭遇し、最終的に を使用しdecodeAsRaster()て convert メソッドに渡しました。

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 に返還されます。基本的には、元の Raster からピクセル配列を取得し、BufferedImage のピクセル配列を取得して、移植性System.arraycopyの高い「高価な」の代わりに実行しますが、 image.setData(raster)、各ピクセルに対して、一貫性とタイプをチェックするためにいくつかのメソッドを呼び出しますが、必要な情報はすべて既にあります。

このコードは に対して有効であるはずですが、BufferedImage.TYPE_INT_RGBテストできなかったことを告白しなければなりませんが、BufferedImage.TYPE_BYTE_GRAY(およびbyte[]/ DataBufferByte) で動作していることはわかっています。

于 2013-03-19T19:11:23.710 に答える
0

JLabel に BufferedImage と ImageIcon を使用する代わりに、DisplayJAI を使用してみましたか? RenderedImage を直接表示できます。

于 2012-03-14T12:43:58.330 に答える
0

レンダリングされた画像をバッファに変更してからjラベルに表示できます.レンダリングされた画像はjai画像であり、jラベルはバッファ画像のみを取り、jaiに表示しようとしないため、jLabelで試してください

于 2014-02-04T05:46:31.153 に答える
0

// 以下のコードで出力をレンダリングできます。String pageNumb = request.getParameter("page"); System.out.println("pageNumb:: "+pageNumb); 文字列 filePath = "/Users/test/Downloads/Multi_page24bpp.tif";

    SeekableStream s = new FileSeekableStream(filePath.trim());
    TIFFDecodeParam param = null;
    ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
    String totNumberOfPage =String.valueOf(dec.getNumPages());
    System.out.println("number of pages:: "+totNumberOfPage);
    RenderedImage op = dec.decodeAsRenderedImage(Integer.parseInt(pageNumb)); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write (op, "jpeg", baos);
//    response = ServletActionContext.getResponse();
    response.setContentType("image/jpeg");
    OutputStream out = response.getOutputStream();
    out.write(baos.toByteArray());
    out.flush();
}
于 2018-09-27T20:04:30.580 に答える