如何使用 LibTIFF 的 TIFFGetField 检索 TIFF 字符串字段?

How are TIFF string fields retrieved using LibTIFF's TIFFGetField?

我一直在尝试使用 LibTiff 的 TIFFGetField 函数读取字符串 TIFF 字段(例如 TIFFTAG_MODEL),但我从中得到的只是指向归零内存的指针。 TIFFGetField man page 没有太大帮助,只是说明它需要一个 char** 字符串字段参数,我认为这暗示它将分配内存,将字符串写入该内存,并且 return 指向它的指针。但是它没有讨论释放内存的责任。

当我定义一个 char* 并将其初始化为 NULL,然后将该变量的地址传递给 TIFFGetField,它确实将其设置为非 NULL 地址,但该地址指向的内存是全为零。

如果相关,我在 MacOS 上使用 LibTiff 4.0.2。

这是我迄今为止尝试过的 MCVE。 (注释掉的代码是我尝试传入一个已经分配的缓冲区的地方。那也没有用。)

#include "tiffio.h"
#include <stdio.h>

const char* img_filename = "temp.tif";

void WriteTestTIFF()
{
    TIFF* tiff = TIFFOpen(img_filename, "w");

    const size_t width = 2;
    const size_t height = 2;
    unsigned char image[width * height] = { 0 };

    TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, height); // Single strip image
    TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
    TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
    TIFFSetField(tiff, TIFFTAG_MINSAMPLEVALUE, 0);
    TIFFSetField(tiff, TIFFTAG_MAXSAMPLEVALUE, 255);

    TIFFSetField(tiff, TIFFTAG_SOFTWARE, "TestingTIFFStringFields");
    TIFFSetField(tiff, TIFFTAG_MODEL, "FakeCamera");

    TIFFWriteEncodedStrip(tiff, 0, image, height * width);
    TIFFClose(tiff);
}

void ReadTestTIFF()
{
    TIFF* tiff = TIFFOpen(img_filename, "r");
    //char buffer[256] = "";
    char* char_ptr = NULL;
    uint32 width = 0;
    uint32 height = 0;
    printf("(void*)char_ptr=0x%016lX\n", (unsigned long)char_ptr);
    //printf("buffer='%s'\n", buffer);
    if ( /*TIFFGetField(tiff, TIFFTAG_MODEL, buffer) != 1
        ||*/ TIFFGetField(tiff, TIFFTAG_MODEL, &char_ptr) != 1
        || TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width) != 1
        || TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height) != 1)
    {
        puts("One or more TIFFGetField calls failed.");
    }
    printf("width=%u\n", width);
    printf("height=%u\n", height);
    TIFFClose(tiff);
    printf("(void*)char_ptr=0x%016lX\n", (unsigned long)char_ptr);
    for (int n=0; n<5; n++)
    {
        printf("char_ptr[%d]=0x%02X\n", n, (unsigned int)(char_ptr[n]));
    }
    //printf("buffer='%s'\n", buffer);
    printf("char_ptr='%s'\n", char_ptr);
}

int main()
{
    WriteTestTIFF();
    ReadTestTIFF();
    return 0;
}

输出:

(void*)char_ptr=0x0000000000000000
width=2
height=2
(void*)char_ptr=0x00007FA5B3400310
char_ptr[0]=0x00
char_ptr[1]=0x00
char_ptr[2]=0x00
char_ptr[3]=0x00
char_ptr[4]=0x00
char_ptr=''

为了证明这些字段被正确写入,这里是生成的 TIFF 文件:

0000000: 4949 2a00 0c00 0000 0000 0000 0e00 0001  II*.............
0000010: 0300 0100 0000 0200 0000 0101 0300 0100  ................
0000020: 0000 0200 0000 0201 0300 0100 0000 0800  ................
0000030: 0000 0301 0300 0100 0000 0100 0000 0601  ................
0000040: 0300 0100 0000 0100 0000 1001 0200 0b00  ................
0000050: 0000 d200 0000 1101 0400 0100 0000 0800  ................
0000060: 0000 1501 0300 0100 0000 0100 0000 1601  ................
0000070: 0300 0100 0000 0200 0000 1701 0400 0100  ................
0000080: 0000 0400 0000 1801 0300 0100 0000 0000  ................
0000090: 0000 1901 0300 0100 0000 ff00 0000 3101  ..............1.
00000a0: 0200 1800 0000 ba00 0000 5301 0300 0100  ..........S.....
00000b0: 0000 0100 0000 0000 0000 5465 7374 696e  ..........Testin
00000c0: 6754 4946 4653 7472 696e 6746 6965 6c64  gTIFFStringField
00000d0: 7300 4661 6b65 4361 6d65 7261 000a       s.FakeCamera..

也许在访问 char_ptr 之前不要 TIFFClose()。它可能会给你一个地址到一些数据结构中,这个数据结构是 created/populated 被 TIFFOpen() 并被 TIFFClose().

销毁