如何在Java中向TIFF添加GPS元数据?

时间:2013-10-15 00:53:17

标签: java gps metadata tiff jai

我正在尝试将GPS数据添加到我用Java创建的TIFF文件中。我正在使用JAI-ImageIO库,尽管如果有更好的库来同时执行G​​PS元数据和自定义元数据,我愿意调查它。

我试图直接将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类型) - 当我将它附加到根时,它似乎只是将它从元数据节点。

1 个答案:

答案 0 :(得分:1)

问题很可能是您正在操作的元数据树表示只是一个工作副本。当您稍后编写图像并将其传递给metadata时,您对树表示的更改将丢失。

使用GPS特定标记更新元数据树(root)后,您必须致电metadata.setFromTree(TIFF_METADATA_FORMAT, root)metadata.mergeTree(TIFF_METADATA_FORMAT, root)将您的更改设置/合并回{ {1}}实例。当您开始使用metadata而不是空结构时,您可能希望使用metadata.getAsTree(..)

PS:如果这不是问题,请在更新元数据的位置添加代码并编写图像。 : - )