2013-10-15 34 views
3

我正在尝试将GPS数据添加到我在Java中创建的TIFF文件中。我正在使用JAI-ImageIO库,但如果有更好的库来完成GPS元数据和自定义元数据,我愿意考虑它。如何将GPS元数据添加到Java中的TIFF?

我试图直接将GPS元数据添加到节点,但它似乎剥离了GPS IDF标签。我试图将GPS IFD添加到TIFFIFD对象(来自TIFFIMageMetadata对象),但似乎没有正确保存数据。

基本上,我正在努力让它正确地保存GPS数据,并试图找出如何获取数据。在互联网上搜索的时间在教程和帮助中几乎没有变化,我没有看到任何有助于Stack Overflow的东西,但是我的搜索功能可能不足。

从我尝试一些代码在通过直接操作的元数据节点做:

RenderedImage img = generateImageSomehow(); 
File writeTarget = new File("blah.tiff"); 
//Get the image writer 
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("tiff"); 
ImageTypeSpecifier specifier = new ImageTypeSpecifier(renderedImage); 
ImageWriter writer = writers.next(); 
//Get the metadata 
IIOMetadata metadata = writer.getDefaultImageMetadata(specifier, writers.getDefaultWriteParam()); 
Node root = metadata.getAsTree(FileConstants.TIFF_METADATA_FORMAT); 
Node ifd = root.getFirstChild(); 
//Create a new IFD node for the GPS data, and add some GPS data to it 
IIOMetadataNode gpsRootNode = new IIOMetadataNode("TIFFIFD"); 
gpsRootNode.setAttribute(FileConstants.TIFF_FIELD_NUMBER_ATTRIBUTE, "34853"); 
gpsRootNode.setAttribute(FileConstants.TIFF_FIELD_NAME_ATTRIBUTE, "GPS"); 
gpsRootNode.setAttribute("tagSets", "com.sun.media.imageio.plugins.tiff.EXIFGPSTagSet"); 
IIOMetadataNode childNode = new IIOMetadataNode(FileConstants.TIFF_FIELD_TAG); 
childNode.setAttribute(FileConstants.TIFF_FIELD_NUMBER_ATTRIBUTE, "1"); 
childNode.setAttribute(FileConstants.TIFF_FIELD_NAME_ATTRIBUTE, "GPSLatitudeRef"); 
IIOMetadataNode asciiNode = new IIOMetadataNode("TIFFAsciis"); 
IIOMetadataNode childAsciiNode = new IIOMetadataNode("TIFFAscii"); 
childAsciiNode.setAttribute(FileConstants.TIFF_FIELD_VALUE_ATTRIBUTE, "N"); 
asciiNode.appendChild(childAsciiNode); 
childNode.appendChild(asciiNode); 
gpsRootNode.appendChild(childNode); 
ifd.appendChild(gpsRootNode); 
//Update metadata with new tree 
metadata.setFromTree(FileConstants.TIFF_METADATA_FORMAT, root); 
ImageOutputStream outstr = ImageIO.createImageOutputStream(writeTarget); 
writer.setOutput(outstr); 
//Write the image 
IIOImage img = new IIOImage(renderedImage, Collections.<BufferedImage> emptyList(), metadata); 
writer.write(img); 
outstr.close(); 

我试图加入的GPS根节点,与对方向的(目前硬编码)值一起。我是否在错误的层面,错误的位置,错误的方式等等?我很好地这样做 - 尽管使用TIFF对象可能会更好。

已更新,以添加额外的代码,以显示我如何创建图像以及如何保存它。


ETA:

这条线的位置:

ifd.appendChild(gpsRootNode); 

实际上应该是:

root.appendChild(gpsRootNode); 

这是我是想了,但是当我做的IFD节点作为我添加GPS节点的节点,我收到一个异常:

Exception in thread "Thread-2" java.lang.ClassCastException: com.sun.media.imageioimpl.plugins.tiff.TIFFIFD cannot be cast to [J 

不知道是否应该在那里 - 看起来它试图将IFD节点强制转换为Long数组(根据标准JNI类型) - 当我将它附加到根时,它似乎删除它来自元数据节点。

+0

是'TIFF_METADATA_FORMAT'“com_sun_media_imageio_plugins_tiff_image_1.0”还是别的? – haraldK

+0

它就是那个文本 - 我从getMetadataFormats()函数中复制了它。 – aperkins

+0

嗯..似乎有一些元数据结构的问题。'TIFFIFD'标签被定义(在DTD中)具有属性“parentTagNumber”和“parentTagName”,而不是“数字”和“名称”。请注意,名称都是多余的,我会在代码中避免它们,以减少冗长。另外,我认为'gpsRootNode'应该是'ifd'的孩子(就像在代码中一样),而不是编辑中的'root'。这是一个次IFD,而不是第二个图像的IFD。 – haraldK

回答

1

问题很可能是您操纵的元数据树表示只是一个工作副本。当您稍后写入图像并通过它metadata时,您对树表示的更改将丢失。

完成后,更新元树(root)与您的GPS特定的标签后,你必须要么调用metadata.setFromTree(TIFF_METADATA_FORMAT, root)metadata.mergeTree(TIFF_METADATA_FORMAT, root)设置/合并更改回metadata实例。当您从metadata.getAsTree(..)开始而不是空的结构时,可能需要使用setFromTree(..)。如果这不是问题,请在您更新元数据并写入图像的位置添加代码。 :-)

+0

这不是问题,因为我在这段代码完成之后这么做 - 我将在今晚将它添加到我回家的时候(这是一个合同项目,而不是我日常工作的一部分) - 我只是忘了将它添加到原来的帖子。 – aperkins

+0

@aperkins好的。去做。或者更好的是,写一个SSCCE。 :-)然后我会删除答案。 – haraldK

+0

用写入部分(和元数据保存部分)更新了问题。我可以尝试获得SSSCCE,但问题是我所使用的数据是保密的,所以我不能真正包含这些数据。基本上,我们有一套我们正在保存的图像数据,而且我对元数据所做的任何其他更改都可以很好地保存,但如果我将GPS IFD添加到它,它只会将其修剪掉。这包括其他自定义节点(如EXIF规范中定义的) – aperkins