Skip to content

Writing a tiled TIFF image with multipages and subIFDs #127

@LionelArn2

Description

@LionelArn2

Hi :)

I've been trying out libtiff.net and it's been working great so far.

I would like to write a tiled TIFF image with multiples pages and subIFDs, are SubIFDs writing supported? I haven't found any such example online, and all my attempts resulted in a corrupted output file where the first 4 bytes do not correspond to a tiff file.

Here's the code I'm working with, could you point me towards anything wrong?

static void Main()
{
    const string path = @"path\to\output\file.tiff";
    const int tileSize = 256;

    using Tiff tiffFile = Tiff.Open(path, "w");

    // Base IFD (full resolution)
    int baseW = 1024;
    int baseH = 1024;
    SetCommonTags(tiffFile, baseW, baseH, tileSize);
    tiffFile.SetField(TiffTag.SUBFILETYPE, FileType.PAGE);

    int subCount = 2;
    int[] subOffsets = new int[subCount]; // placeholders (all zeros)
    tiffFile.SetField(TiffTag.SUBIFD, (short)subCount, subOffsets);

    WriteAllBlackTiles(tiffFile, baseW, baseH, tileSize);
    tiffFile.WriteDirectory();

    // SubIDFs (reduced resolutions)
    int w2 = baseW, h2 = baseH;
    for (int i = 0; i < subCount; i++)
    {
        // next reduced size
        w2 = Math.Max(1, w2 / 2);
        h2 = Math.Max(1, h2 / 2);

        tiffFile.CreateDirectory();

        SetCommonTags(tiffFile, w2, h2, tileSize);
        tiffFile.SetField(TiffTag.SUBFILETYPE, FileType.REDUCEDIMAGE);

        WriteAllBlackTiles(tiffFile, w2, h2, tileSize);
        tiffFile.WriteDirectory();
    }
}

static void SetCommonTags(Tiff t, int width, int height, int tile)
{
    t.SetField(TiffTag.IMAGEWIDTH, width);
    t.SetField(TiffTag.IMAGELENGTH, height);
    t.SetField(TiffTag.SAMPLESPERPIXEL, 1);
    t.SetField(TiffTag.BITSPERSAMPLE, 8);
    t.SetField(TiffTag.SAMPLEFORMAT, SampleFormat.UINT);
    t.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
    t.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
    t.SetField(TiffTag.COMPRESSION, Compression.LZW);
    t.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);

    // tiled layout
    t.SetField(TiffTag.TILEWIDTH, tile);
    t.SetField(TiffTag.TILELENGTH, tile);

    // (optional) resolution metadata
    t.SetField(TiffTag.XRESOLUTION, 72.0);
    t.SetField(TiffTag.YRESOLUTION, 72.0);
    t.SetField(TiffTag.RESOLUTIONUNIT, ResUnit.INCH);

}

static void WriteAllBlackTiles(Tiff t, int width, int height, int tile)
{
    // 8-bit black tile
    byte[] buf = new byte[tile * tile];

    for (int y = 0; y < height; y += tile)
    {
        for (int x = 0; x < width; x += tile)
        {
            int tileIndex = t.ComputeTile(x, y, 0, 0);
            int written = t.WriteEncodedTile(tileIndex, buf, buf.Length);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions