1

システム(Tomcatで実行されているJavaアプリ)のパフォーマンスを向上させようとしていますが、ボトルネックが1つの操作にあるため、tiff画像のディメンションを読み取って返す必要があるため、JAIのImageDecoderを使用して使用します。

ImageDecoder decoder = ImageCodec.createImageDecoder("TIFF", input, param);
RenderedImage r = decoder.decodeAsRenderedImage();
int width = r.getWidth();
int height = r.getHeight();

データのサンプリングから、createImageDecoderに多くの時間が費やされます。私の仮定(ImageCodecのソースコードに行かなくても)は、おそらく入力ストリームをデコードしようとしているということです。

Androidの世界から来て、設定のように境界をデコードするだけの同様のソリューションがあることを望んでいますBitmapFactory.Options.inJustDecodeBounds = trueが、これまでのところ、そのような他のライブラリを見つけることはできません。(AndroidでのtiffサポートがAOSPにないことは承知していますが、それは別の日のトピックです。)

誰もがこれを行うライブラリを知っていますか?または、JAI / ImageIOを使用して同様の目標を達成する方法はありますか?

4

1 に答える 1

1

tiffファイル形式はこの情報をヘッダーにグループ化するように見えるので、ファイルからデータを自分で読み取ることができます。

private static Dimension getTiffDimensions(InputStream tiffFile) throws IOException {
    ReadableByteChannel channel = Channels.newChannel(tiffFile);

    ByteBuffer buffer = ByteBuffer.allocate(12);

    forceRead(channel, buffer, 8);
    byte endian = buffer.get();
    if(endian != buffer.get() || (endian != 'I' && endian != 'M')) {
        throw new IOException("Not a tiff file.");
    }

    buffer.order(endian == 'I' ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
    if(buffer.getShort() != 42) {
        throw new IOException("Not a tiff file.");
    }

    // Jump to the first image directory. Note that we've already read 8 bytes.
    tiffFile.skip(buffer.getInt() - 8);

    int width = -1;
    int height = -1;
    // The first two bytes of the IFD are the number of fields.
    forceRead(channel, buffer, 2);
    for(int fieldCount = buffer.getShort(); fieldCount > 0 && (width < 0 || height < 0); --fieldCount) {
        forceRead(channel, buffer, 12);
        switch(buffer.getShort()) {
        case 0x0100: // Image width
            width = readField(buffer);
            break;
        case 0x0101: // Image "length", i.e. height
            height = readField(buffer);
            break;
        }
    }
    return new Dimension(width, height);
}

private static void forceRead(ReadableByteChannel channel, ByteBuffer buffer, int n) throws IOException {
    buffer.position(0);
    buffer.limit(n);

    while(buffer.hasRemaining()) {
        channel.read(buffer);
    }
    buffer.flip();
}

private static int readField(ByteBuffer buffer) {
    int type = buffer.getShort();
    int count = buffer.getInt();

    if(count != 1) {
        throw new RuntimeException("Expected a count of 1 for the given field.");
    }

    switch(type) {
    case 3: // word
        return buffer.getShort();
    case 4: // int
        return buffer.getInt();
    default: // char (not used here)
        return buffer.get() & 0xFF;
    }
}

私はこれをいくつかの異なるtiffファイル(ランレングスでエンコードされた白黒、透明度のある色)でテストしましたが、正常に機能しているようです。tiffファイルのレイアウトによっては、サイズを見つける前に多くのストリームを読み取らなければならない場合があります(Appleのプレビューによって保存されたテストしたファイルの1つで、ファイルの最後にこのデータがありました)。

于 2013-03-27T17:15:35.900 に答える