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

时间:2016-11-09 00:36:45

标签: c libtiff

我一直在尝试使用LibTiff的TIFFGetField函数读取字符串TIFF字段(例如TIFFTAG_MODEL),但我从中获取的所有内容都是指向归零内存的指针。 TIFFGetField man page没有多大帮助,只是声明它需要一个char**字符串字段的参数,我认为它暗示它会分配内存,将字符串写入该内存,然后返回一个指向它的指针。但是,它并没有讨论释放这种记忆的责任。

当我定义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..

1 个答案:

答案 0 :(得分:2)

在访问TIFFClose()之前,或许不要char_ptr。它可能会将您的地址返回到由TIFFOpen()创建/填充的某些数据结构中,并由TIFFClose()销毁。