Java 解析Tiff深入研究

最近在读取客户发过来的tiff文件是,底层竟然报错了,错误: bandOffsets.length is wrong!  没办法,因为错误消息出现在tiff的read中,因此就对底层序中tiff读取的代码进行了研究。

借助这篇文章,我们需要先了解Tiff文件的具体结构,可以参考这篇文章, TIFF文件结构详解 https://blog.csdn.net/oYinHeZhiGuang/article/details/121710467  讲的很好!

下面我们来看下imageio-ext中的tiff读取代码,主要类TiffImageReader,我们来看下Java程序是如何读取tiff文件的。

构造方法:

public TIFFImageReader(ImageReaderSpi originatingProvider) {
        super(originatingProvider);
 }

这个类需要通过一个ImageReaderSpi来实例化,其实这种SPI的设计模式,Java的很多开源项目都在用到,这里我们通过TIFFImageReaderSpi这个类即可。

其次设置文件的路径,以及其它一些参数,通过该类的如下方法:

public void setInput(Object input,
                         boolean seekForwardOnly,
                         boolean ignoreMetadata)

这个方法,里面有input就是需要读取的文件, seekForwardOnly设置为true表示: 只能从这个输入源按升序读取图像和元数据。 ignoreMetadata设置为true表示读取忽略元数据

接下来就是对tiff元数据的读取,具体参见getImageMetadata(int imageIndex)这个方法:

public IIOMetadata getImageMetadata(int imageIndex) throws IIOException {
        seekToImage(imageIndex, true);
        TIFFImageMetadata im =
            new TIFFImageMetadata(imageMetadata.getRootIFD().getTagSetList());
        Node root =
            imageMetadata.getAsTree(TIFFImageMetadata.nativeMetadataFormatName);
        im.setFromTree(TIFFImageMetadata.nativeMetadataFormatName, root);
        if (noData != null) {
            im.setNoData(new double[] {noData, noData});
        }
        if (scales != null && offsets != null) {
            im.setScales(scales);
            im.setOffsets(offsets);
        }
        return im;
    }

其中的seekToImage(imageIndex, true)为最主要的逻辑处理,这个方法中,第一个参数,imageIndex为tiff多页中的第几个,第二参数设置标示该tiff页是否已经被解析过

 private void seekToImage(int imageIndex, boolean optimized) throws IIOException {
        checkIndex(imageIndex);

        // TODO we should do this initialization just once!!!
        int index = locateImage(imageIndex);
        if (index != imageIndex) {
            throw new IndexOutOfBoundsException("imageIndex out of bounds!");
        }
        
        final Integer i= Integer.valueOf(index);
        //optimized branch
        if(!optimized){
            
            readMetadata();
            initializeFromMetadata();
            return;
        }
        // in case we have cache the info for this page
        if(pagesInfo.containsKey(i)){
            // initialize from cachedinfo only if needed
            // TODO Improve
            if(imageMetadata == null || !initialized) {// this means the curindex has changed
                final PageInfo info = pagesInfo.get(i);
                final TIFFImageMetadata metadata = info.imageMetadata.get();
                if (metadata != null) {
                    initializeFromCachedInfo(info, metadata);
                    return;
                }
                pagesInfo.put(i,null);
                    
            }
        }
        
        readMetadata();
        initializeFromMetadata();
    }

这个方法当中,第一次加载tiff,通过readMetadata()和initializeFromMetadata()将tiff的元信息缓存起来,方便后面再次读取。

读取过程

主要是要结合Tiff的格式进行理解,大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值