LibTIFF:从TIFF图像中提取所有标签

7

我目前正在开发一个项目,需要将TIFF图像拆分成一个包含所有标签的文件和一个包含所有图像数据的文件,并从这些文件重构TIFF图像。唯一的问题是,似乎LibTIFF没有提供一种简单的方法来获取图像中的所有标签。我尝试使用TIFFGetTagListCount和TIFFGetField来检索标签,但这只返回了一小部分标签。我已经开始编写自己的版本,但我只想再次确认并确保我没有忽略任何东西,因为这似乎是应该包含在库中的一个非常明显的功能。


你好奇地问,你找到解决这个问题的方法了吗? - Anish Ramaswamy
6个回答

5

以下是最接近扫描所有标记的方法:

 #include "LibTIFF/tif_dir.h"
 ...

 TIFFDirectory *td = &tif->tif_dir;

 for (int fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
    const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];

    // test if tag value is set
    // (lifted directly form LibTiff _TIFFWriteDirectory)

        if( fip->field_bit == FIELD_CUSTOM ) {
            int ci, is_set = FALSE;

            for( ci = 0; ci < td->td_customValueCount; ci++ )
                is_set |= (td->td_customValues[ci].info == fip);

            if( !is_set )
                continue;
        } else if(!TIFFFieldSet(tif, fip->field_bit))
            continue;

        // else: process the fip->field_tag


    }

请注意,一些标签会出现两次(长版本和短版本),但是只有一个版本具有值。正确的类型可以在包含的标题中查找(TIFFDirectory结构体)。
还有其他注意事项,如何读取标签,但这至少会使您循环遍历它们(标准标签)。如果卡住了,请参考tif_dirinfo.c。

由于 tif_dir.h 是一个内部头文件(即不被构建库公开),因此在包含它时会导致各种问题,如重定义、缺少依赖项等。有其他解决方法吗? - Anish Ramaswamy
@Anish Ramaswamy 我不知道有没有。正如所说,这是从LibTIFF源代码中反向工程出来的。如果您遇到重新定义的问题,请尝试将其隔离在单独的翻译单元或小型库中。至于缺少的声明 - 还必须添加其他包含文件。如果我没记错,只需要头文件即可,无需编译任何lib中的.c文件。 - user362515
那似乎很不优雅。我还在寻找中。谢谢! - Anish Ramaswamy

4

使用tifffile打印所有标签:

from tifffile import TiffFile
for page in TiffFile(path_to_file).pages:
    for tag in page.tags.values():
        print(tag.name, tag.code, tag.dtype, tag.count, tag.value)

另外,tifffile.py似乎不支持LZW压缩的tiff文件。 - matth
1
@matth 它确实支持它们(甚至在2018年10月就已经支持了),但前提是满足对 imagecodecs 的可选依赖。 - Alex Shpilkin

1

您可以使用图像的tif_dir字段。它是一个结构体,至少包含以下字段:

  • td_customValueCount 包含“自定义”标签计数的数量,
  • td_customValuestd_customValueCount个标签值(从0开始索引)的列表,并且是TIFFTagValue *类型。

因此,您应该能够像这样做(按照在线代码的真实方式,当然没有经过测试!):

for (i=0; i < tiffimage->tif_dir->td_customValueCount; ++i) {
    const TIFFFieldInfo *info = tiffimage->tif_dir->td_customValues[i].info;
    const char *tagname = info->field_name();
    /* process tag */
}

请参考TIFFDirectory结构体参考。希望能帮到你。

1

非标准标签实际上不是问题,因为简单的标准标签如TIFF_IMAGEWIDTH和TIFF_IMAGELENGTH似乎没有包括在标签列表计数中。这真的很奇怪。 - Eric Scrivner

0

tiffdump 实用程序(随 libtiff 一起提供)可以实现此功能,但是查看代码后,似乎它们主要是在绕过库进行工作。实际上,它们调用 lseekread 来读取标签信息。


0

修正了cgohlke答案中for循环的问题。同时扩展了更完整的脚本,以便更容易地从命令行运行。

import sys, getopt
from tifffile import TiffFile

def PrintAll(path_to_file):
    print('Tag.Name, Tag.Code, Tag.DType, Tag.Count, Tag.Value')
    for page in TiffFile(path_to_file).pages:
        for tag in page.tags.values():
            print(tag.name, tag.code, tag.dtype, tag.count, tag.value)

def main(argv):
    try:
        opts, args = getopt.getopt(argv, 'hi:v', ["help","image="])
    except getopt.GetoptError:
        print('Argv error')
        sys.exit(2)
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            print('printalltifftags.py -i c:\images\myimage.tif')
            sys.exit(0)
        elif opt in ('-i', '--image'):
            filePath = arg
    print('Image: ' + filePath)
    PrintAll(filePath)

if __name__ == '__main__':
    main(sys.argv[1:])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接