lottie json java 解析 工具类 java解析tif数据

您所在的位置:网站首页 java读取json数据 lottie json java 解析 工具类 java解析tif数据

lottie json java 解析 工具类 java解析tif数据

2023-05-26 17:47| 来源: 网络整理| 查看: 265

最近在读取客户发过来的tiff文件是,底层竟然报错了,错误:bandOffsets.length is wrong! 

底层序中tiff读取的代码进行了研究。

       之前有一篇文章,我简单的介绍了Geotools读取Tiff的代码,Java 通过geotools读取tiff,其实通过深入研究发现,原来幕后的大佬竟然是imageio-ext中的TiffImageReader,

imageio做为Java开发的人员肯定都知道,而ImageIO-ext是imageio的扩展类,我们可以到github上看到它的源码,这是一个非常强大的库,对于Java处理各种栅格数据的读写非常有帮助!

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的格式进行理解,大体主要是解析tiff头,然后获取到IFD(tiff的图像目录信息),然后再依次去解析每个目录的具体内容,代码就不再这里罗列了。

这里主要说下,解析目录信息是获取tiff的元信息的过程,通常是解析每个tag的信息,解析代码TIFFIFD类的initialize(ImageInputStream stream,  boolean ignoreUnknownFields, final boolean isBTIFF)方法中

lottie json java 解析 工具类 java解析tif数据_元数据

lottie json java 解析 工具类 java解析tif数据_Java_02

public void initialize(ImageInputStream stream, boolean ignoreUnknownFields, final boolean isBTIFF) throws IOException { removeTIFFFields(); List tagSetList = getTagSetList(); final long numEntries; if(isBTIFF) numEntries= stream.readLong(); else numEntries= stream.readUnsignedShort(); for (int i = 0; i < numEntries; i++) { // Read tag number, value type, and value count. int tag = stream.readUnsignedShort(); int type = stream.readUnsignedShort(); int count; if(isBTIFF) { long count_=stream.readLong(); count = (int)count_; if(count!=count_) throw new IllegalArgumentException("unable to use long number of values"); } else count = (int)stream.readUnsignedInt(); // Get the associated TIFFTag. TIFFTag tiffTag = getTag(tag, tagSetList); // Ignore unknown fields. if(ignoreUnknownFields && tiffTag == null) { // Skip the value/offset so as to leave the stream // position at the start of the next IFD entry. if(isBTIFF) stream.skipBytes(8); else stream.skipBytes(4); // XXX Warning message ... // Continue with the next IFD entry. continue; } long nextTagOffset; if(isBTIFF){ nextTagOffset = stream.getStreamPosition() + 8; int sizeOfType = TIFFTag.getSizeOfType(type); if (count*sizeOfType > 8) { long value = stream.readLong(); stream.seek(value); } } else{ nextTagOffset = stream.getStreamPosition() + 4; int sizeOfType = TIFFTag.getSizeOfType(type); if (count*sizeOfType > 4) { long value = stream.readUnsignedInt(); stream.seek(value); } } if (tag == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tag == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = stream.getStreamPosition(); if (LAZY_LOADING) { type = type == TIFFTag.TIFF_LONG ? TIFFTag.TIFF_LAZY_LONG : TIFFTag.TIFF_LAZY_LONG8; } } else if (tag == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tag == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = stream.getStreamPosition(); if (LAZY_LOADING) { type = type == TIFFTag.TIFF_LONG ? TIFFTag.TIFF_LAZY_LONG : TIFFTag.TIFF_LAZY_LONG8; } } Object obj = null; try { switch (type) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_ASCII: byte[] bvalues = new byte[count]; stream.readFully(bvalues, 0, count); if (type == TIFFTag.TIFF_ASCII) { // Can be multiple strings final List v = new ArrayList(); boolean inString = false; int prevIndex = 0; for (int index = 0; index


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3