在Java/JAI中,是否有相当于Android的BitmapFactory.Options isDecodeBounds for TIFF?



我试图提高我们的系统(一个Java应用程序在Tomcat中运行)的性能,现在的瓶颈是在一个操作中,我们需要读取和返回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,但到目前为止没有找到任何其他库这样的运气。(我知道在AOSP中没有对Android的tiff支持,但这是另一天的话题。)

有谁知道这样做的库吗?或者是否有一种方法可以使用ai/ImageIO实现类似的目标?

看起来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的Preview保存,在文件末尾有这个数据)。

最新更新