首页 > 解决方案 > 从 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.get​TIFFField(306); 
    String dateString = dateTime.getAsString(0);  
}

但它没有给出标签的确切值。如果是非 ASCII 值(ö、ü、ä 等),问号会替换实际值。

谁能告诉我如何从 TIFFField 获取标签的确切值(包括非 ASCII)?

标签: utf-8tiffjava-11non-ascii-characters

解决方案


您可以使用标准 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.get​TIFFField(306); // Yes, that's 3 F's...
    String dateString = dateTime.getAsString(0); // TIFF dates are strings...
}

tiffFile必须是有效的(现有的,可读的)java.io.Filejava.io.RandomAccessFilejava.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+ 的方法更简洁,更容易推理。


推荐阅读