utf-8 - 从 Java 11 中的 TIFF 图像中获取 TIFF 标签值(包括非 ASCII 字符)
问题描述
我正在尝试从 Java 中的 TIFF 图像中读取不同的标签值(如标签 259(压缩)、33432(版权)、306(日期时间)、315(艺术家)等)。谁能建议在 Java 11 中获取这些值的最佳方法是什么?
我尝试使用 tiffinfo 命令(如“ tiffinfo -c myfile.tif
”)获取这些值。但我在 tiffinfo (libtiff) 或任何 Java 库中没有找到任何特定命令,这些命令将为我提供 TIFF 图像的特定标记值(例如 DateTime)。
更新:
正如 haraldK 建议的那样,我尝试使用 ImageIO,如下所示
try (ImageInputStream input = ImageIO.createImageInputStream(tiffFile)) {
ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle reader not found
reader.setInput(input);
IIOMetadata metadata = reader.getImageMetadata(0);
TIFFDirectory ifd = TIFFDirectory.createFromMetadata(metadata);
TIFFField dateTime = ifd.getTIFFField(306);
String dateString = dateTime.getAsString(0);
}
但它没有给出标签的确切值。如果是非 ASCII 值(ö、ü、ä 等),问号会替换实际值。
谁能告诉我如何从 TIFFField 获取标签的确切值(包括非 ASCII)?
解决方案
您可以使用标准 ImageIO,读取 TIFF 图像元数据并从中获取请求的值,例如通过使用 JDK 中的一些额外支持类,从 Java 9 开始:
try (ImageInputStream input = ImageIO.createImageInputStream(tiffFile)) {
ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle reader not found
reader.setInput(input);
IIOMetadata metadata = reader.getImageMetadata(0); // 0 is the index of first image
TIFFDirectory ifd = TIFFDirectory.createFromMetadata(metadata);
TIFFField dateTime = ifd.getTIFFField(306); // Yes, that's 3 F's...
String dateString = dateTime.getAsString(0); // TIFF dates are strings...
}
tiffFile
必须是有效的(现有的,可读的)java.io.File
,java.io.RandomAccessFile
或java.io.InputStream
(或其他受支持的输入,这实际上是基于插件的)。如果不是,input
将是null
,并且代码将失败。
只要您有 TIFF 插件,您就可以使用类似但更详细的版本,该版本适用于旧版本的 Java:
try (ImageInputStream input = ImageIO.createImageInputStream(tiffFile)) {
ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle reader not found
reader.setInput(input);
IIOMetadata metadata = reader.getImageMetadata(0); // 0 is the index of first image
// Get "native" TIFF metadata for first IFD
IIOMetadataNode root = metadata.getAsTree("com_sun_media_imageio_plugins_tiff_image_1.0");
Node ifd = root.getFirstChild();
NodeList fields = ifd.getElementsByTagName("TIFFField"); // Yes, that's 3 F's...
for (int i = 0; i < fields.getLength(); i++) {
Element field = (Element) fields.item(i);
if ("306".equals(field.getAttribute("number"))) {
// This is your DateTime (306) tag,
// now do something with it
// ...
}
}
}
但是,几乎没有优雅的代码……Java 9+ 的方法更简洁,更容易推理。