我正在努力提高我们系统(在Tomcat中运行的Java应用程序)的性能,现在瓶颈在一个操作中,我们需要读取并返回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支持,但这是另一天的主题。)
有人知道这样做的图书馆吗?或者有没有办法使用JAI / ImageIO实现类似的目标?
答案 0 :(得分:1)
看起来tiff file format将此信息组合在一个标题中,因此您可以自己从文件中读取数据:
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的预览保存,在文件的末尾有这些数据)。