如何使用 LibTIFF 在多页上写入图块

How to write tiles on multi pages using LibTIFF

我正在尝试使用 LibTIFF 在多页 tiff(金字塔形 tiff)上编写图块:

for(int pageNum=0; pageNum<pageCount; pageNum++)
{
    // processing for getting tiles (decode and resize for each page)
    ////

    TIFFSetField(tiff_out, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
    TIFFSetField(tiff_out, TIFFTAG_PAGENUMBER, pageNum);
    //TIFFSetField(tiff_out, TIFFTAG_IMAGEWIDTH, imageWidth); // <- cannot be done with en error message(cannot change the value while processing)
    //TIFFSetField(tiff_out, TIFFTAG_IMAGELENGTH, imageHeight); // <- cannot be done with en error message(cannot change the value while processing)
    TIFFWriteEncodedTile(tiff_out, tileNumberOnPage, buff, -1);   
}

当我尝试只写单页时,我工作得很好。 但是当尝试处理多页时,结果会显示重叠的图像。 似乎所有页面都显示在第一页。

我用 tiffinfo 命令检查了生成的 TIFF 文件。 显示页码是最后一页,但只显示第一页的信息(即只显示一页)

在多页、金字塔形 TIFF 上是否有其他设置来写入图块?

(我也尝试将 FILETYPE_PAGE 设置为 TIFFTAG_SUBFILETYPE。)

要创建 mutliple pages (directories) in the TIFF file,请使用 TIFFWriteDirectory 函数。它将指定的标签和数据写入当前目录,并开始一个新目录。 TIFFClose 将标签和数据写入当前目录并关闭文件。

因此,要创建一个包含两个目录的文件,您首先要创建一个新文件,设置标签并写入磁贴,调用TIFFWriteDirectory,设置标签并写入磁贴,然后调用TIFFClose

例如,您可以将代码修改为:

for(int pageNum=0; pageNum<pageCount; pageNum++)
{
    // processing for getting tiles (decode and resize for each page)
    if(pageNum>0) {
        TIFFWriteDirectory(tiff_out);
    }
    TIFFSetField(tiff_out, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
    TIFFSetField(tiff_out, TIFFTAG_IMAGEWIDTH, imageWidth);
    TIFFSetField(tiff_out, TIFFTAG_IMAGELENGTH, imageHeight);
    TIFFWriteEncodedTile(tiff_out, tileNumberOnPage, buff, -1);   
}
TIFFClose(tiff_out);

我找到了这个版本 https://www.asmail.be/msg0055065771.html 最有帮助的。一个警告,确保使用已声明的 uint16 用于 spp、bpp、照片,以及 res_unit、uint32 用于宽度和高度, xres 和 yres 的 float。 否则 va_args 将无法为您的 tiff 文件获取正确的值。

我还发现有用的 TIFFTAG_SOFTWARE 和 TIFFTAG_DATETIME 是字符串,但不包括在下面的示例中。

我还把 TIFFTAG_IMAGEWIDTH 的原件从 image_width / spp 改成了 just image_width,这对我的彩色图像 (3) 不正确。

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

#define XSIZE 256
#define YSIZE 256
#define NPAGES 10

int main (int argc, char **argv)
{
    uint32 image_width, image_height;
    float xres, yres;
    uint16 spp, bpp, photo, res_unit;
    TIFF *out;
    int i, j;
    uint16 page;

    unsigned char array[XSIZE * YSIZE];

    for (j = 0; j < YSIZE; j++)
            for(i = 0; i < XSIZE; i++)
                    array[j * XSIZE + i] = (unsigned char)(i * j);

    out = TIFFOpen("out.tif", "w");
    if (!out)
    {
            fprintf (stderr, "Can't open %s for writing\n", argv[1]);
            return 1;
    }
    image_width = XSIZE;
    image_height = YSIZE;
    spp = 1; /* Samples per pixel */
    bpp = 8; /* Bits per sample */
    photo = PHOTOMETRIC_MINISBLACK;

    for (page = 0; page < NPAGES; page++)
    {
        TIFFSetField(out, TIFFTAG_IMAGEWIDTH, image_width);
        TIFFSetField(out, TIFFTAG_IMAGELENGTH, image_height);
        TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bpp);
        TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
        TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photo);
        TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
        /* It is good to set resolutions too (but it is not nesessary) */
        xres = yres = 100;
        res_unit = RESUNIT_INCH;
        TIFFSetField(out, TIFFTAG_XRESOLUTION, xres);
        TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
        TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, res_unit);

        /* We are writing single page of the multipage file */
        TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
        /* Set the page number */
        TIFFSetField(out, TIFFTAG_PAGENUMBER, page, NPAGES);

        for (j = 0; j < image_height; j++)
            TIFFWriteScanline(out, &array[j * image_width], j, 0);

        TIFFWriteDirectory(out);
    }

    TIFFClose(out);

    return 0;
}