如何使用 LibTIFF 在多页面上编写磁贴

How to write tiles on multi pages using LibTIFF

本文关键字:何使用 LibTIFF      更新时间:2023-10-16

我正在尝试使用 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

要在 TIFF 文件中创建多个页面(目录),请使用 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 表示宽度和高度,并浮动 xre 和 yres。否则,va_args将无法为您的 tiff 文件获取正确的值。

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

我还将TIFFTAG_IMAGEWIDTH的原始版本从 image_width/spp 更改为仅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 writingn", 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;
}