在Java / JAI中是否有相当于Android的BitmapFactory.Options isDecodeBounds for TIFF? [英] Is there a equivalent of Android's BitmapFactory.Options isDecodeBounds for TIFF in Java/JAI?

查看:162
本文介绍了在Java / JAI中是否有相当于Android的BitmapFactory.Options isDecodeBounds for TIFF?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力提高我们系统(在Tomcat中运行的Java应用程序)的性能,现在瓶颈在一个操作中,我们需要读取并返回tiff图像的维度,所以我们使用JAI的ImageDecoder并使用

I am trying to improve the performance of our system (a Java app running in Tomcat) and now the bottleneck is in one operation, we need to read and return dimension of tiff images, so we use JAI's ImageDecoder and use

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

从采样数据中,在createImageDecoder中花费了大量时间。我的假设(没有去ImageCodec的源代码)是它可能试图解码输入流。

From sampling data, a lot of time is spent in createImageDecoder. My assumption (without going to source code of ImageCodec) is it's probably trying to decode the input stream.

来自Android版本,我希望有一个类似的解决方案来解码边界,如设置 BitmapFactory.Options.inJustDecodeBounds = true 但到目前为止还没有找到任何其他类似的库。 (我知道AOSP中缺少对Android的tiff支持,但这是另一天的主题。)

Coming from Android land, I am hoping there is a similar solution to just decode bounds like setting BitmapFactory.Options.inJustDecodeBounds = true but so far no luck in finding any other library like that. (I am aware that tiff support on Android is missing in AOSP, but that's topic for another day.)

任何人都知道这样做的库吗?或者有没有办法使用JAI / ImageIO实现类似目标?

Anyone know a library that does this? Or is there a way to achieve similar goal using JAI/ImageIO?

推荐答案

它看起来像 tiff文件格式将这些信息组合在一个标题中,这样您就可以自己从文件中读取数据:

It looks like the tiff file format groups this information together in a header, so you could just read the data from the file yourself:

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的预览保存,在文件的末尾有这些数据)。

I've tested this with a few different tiff files (run length encoded black & white, color with transparency) and it seems to work fine. Depending on the layout of your tiff file it may have to read a lot of the stream before it finds the size (one of the files I tested, saved by Apple's Preview, had this data at the end of the file).

这篇关于在Java / JAI中是否有相当于Android的BitmapFactory.Options isDecodeBounds for TIFF?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆