Search code examples
c#.nettiffimaginglibtiff.net

Create a Bigtiff (>4GB) File with Bitmiracle Libtiff.net


First I want to thank Bitmiracle for this great lib. Even while creating very big files, the memory footprint is very low. A few days ago I ran into a problem where I wanted to create a tiff file bigger than 4GB. I created the tiled tiff file successfully, but it seems that the color of the tiles created beyond 4GB are somehow inverted.

Resulted File viewed with vilv viewer Here the code relevant code:

Usage:

WriteTiledTiff("bigtiff.tiff",BitmapSourceFromBrush(new RadialGradientBrush(Colors.Aqua,Colors.Red), 256));

Methods:

public static BitmapSource BitmapSourceFromBrush(Brush drawingBrush, int size = 32, int dpi = 96)
    {
        // RenderTargetBitmap = builds a bitmap rendering of a visual
        var pixelFormat = PixelFormats.Pbgra32;
        RenderTargetBitmap rtb = new RenderTargetBitmap(size, size, dpi, dpi, pixelFormat);

        // Drawing visual allows us to compose graphic drawing parts into a visual to render
        var drawingVisual = new DrawingVisual();
        using (DrawingContext context = drawingVisual.RenderOpen())
        {
            // Declaring drawing a rectangle using the input brush to fill up the visual
            context.DrawRectangle(drawingBrush, null, new Rect(0, 0, size, size));
        }

        // Actually rendering the bitmap
        rtb.Render(drawingVisual);
        return rtb;
    }

public static void WriteTiledTiff(string fileName, BitmapSource tile)
    {
        const int PIXEL_WIDTH = 48000;
        const int PIXEL_HEIGHT = 48000;

         int iTile_Width = tile.PixelWidth;
         int iTile_Height = tile.PixelHeight;

        using (Tiff tiff = Tiff.Open(fileName, "w"))
        {
            tiff.SetField(TiffTag.IMAGEWIDTH, PIXEL_WIDTH);
            tiff.SetField(TiffTag.IMAGELENGTH, PIXEL_HEIGHT);
            tiff.SetField(TiffTag.COMPRESSION, Compression.NONE);
            tiff.SetField(TiffTag.PHOTOMETRIC, Photometric.RGB);

            tiff.SetField(TiffTag.ROWSPERSTRIP, PIXEL_HEIGHT);

            tiff.SetField(TiffTag.XRESOLUTION, 96);
            tiff.SetField(TiffTag.YRESOLUTION, 96);

            tiff.SetField(TiffTag.BITSPERSAMPLE, 8);
            tiff.SetField(TiffTag.SAMPLESPERPIXEL, 3);

            tiff.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);

            tiff.SetField(TiffTag.TILEWIDTH, iTile_Width);
            tiff.SetField(TiffTag.TILELENGTH, iTile_Height);

            int tileC = 0;
            for (int row = 0; row < PIXEL_HEIGHT; row += iTile_Height)
            {
                for (int col = 0; col < PIXEL_WIDTH; col += iTile_Width)
                {
                    if (tile.Format != PixelFormats.Rgb24) tile = new FormatConvertedBitmap(tile, PixelFormats.Rgb24, null, 0);
                    int stride = tile.PixelWidth * ((tile.Format.BitsPerPixel + 7) / 8);

                    byte[] pixels = new byte[tile.PixelHeight * stride];
                    tile.CopyPixels(pixels, stride, 0);

                    tiff.WriteEncodedTile(tileC++, pixels, pixels.Length);
                }
            }

            tiff.WriteDirectory();
        }
    }

The resulted file will be 6,47GB in size. I viewed it with a small tool called "vliv" vilv download


Solution

  • All LibTiff.Net versions including 2.4.500.0 are based on 3.x branch of the original libtiff.

    Support for BigTIFF was introduced in 4.x branch of the original libtiff. Thus, at this time there are no LibTiff.Net versions designed to handle BigTiff files / files over 4GB on disk.

    EDIT:

    LibTiff.Net 2.4.508 adds support for BigTiff.