从Java 11中的TIFF图像中获取TIFF标记值包括非ASCII字符

问题描述

我正在尝试从Java中的TIFF图像读取不同的标签值(例如259(压缩),33432(版权),306(DateTime),315(Artist)等)。谁能建议在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)?

解决方法

您可以使用标准ImageIO,读取TIFF图像元数据并从中获取请求的值,例如通过从Java 9开始在JDK中使用一些额外的支持类来实现:

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+方法更简洁,更容易推理。