Open huge TIF in .NET and copy parts to new image

房东的猫 提交于 2019-11-28 10:53:39

If your file is less than 4GB on disk than I recommend you to take another look at LibTiff.Net. Even with such large images you have some options.

First of all, check whether your image is tiled or stripped. Tiff.IsTiled method will give you the answer.

If your image is tiled, than you probably shouldn't read it using ReadScanline method. It might be better to use ReadEncodedTile method in that case.

If your images is stripped, than you can use ReadScanline and ReadEncodedStrip methods to read it.

If you want to use something that expects System.Drawing.Bitmap than try using ReadRGBATile or ReadRGBAStrip. These methods can be used to create bitmaps from portions of your image. There is no sample for this, but Convert color TIFF to a 32-bit System.Drawing.Bitmap should give you almost all required information about how to convert tile or strip of an image to a bitmap.

EDIT:

LibTiff.Net 2.4.508 adds support for BigTiff so files larger than 4GB are also supported.

Your image must be in BigTIFF format, since normal TIFF can't be larger than 4 GB.

BigTIFF can be read with a modified version of libtiff (available in BigTIFF website), this library allows to handle such images the way you want without loading all pixel data in memory.

I didn't see bindings for .NET but it shouldn't be too long to do it.

Atalasoft dotImage has this ability built-in to the TIFF decoder. The decode implements the interface IRegionReadable, which lets you read a rectangular section from a given page of an image in a Stream.

In a TIFF, this section will honor the orientation tag and in stripped or tiled tiffs uses the minimum set of tiles and strips to fill the rectangle.

(disclaimer, I work for Atalasoft and wrote that interface and implemented it in the TIFF decoder)

As Bobrovsky mentioned you should check if your file image is tiled or not. In the following, I've presented the snippet code to read a stream tiff and crop the upper left part of the image.

using (Tiff input = Tiff.Open(@"imageFile.tif", "r"))
        {
            // get properties to use in writing output image file
            int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
            int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
            int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
            int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
            int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();

            int scanlineSize = input.ScanlineSize();    
            byte[][] buffer = new byte[height][]; 
            for (int i = 0; i < height; ++i)
            {
                buffer[i] = new byte[scanlineSize];
                input.ReadScanline(buffer[i], i);
            }



            using (Tiff output = Tiff.Open("splitedImage.tif", "w"))
            {
                output.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel);
                output.SetField(TiffTag.IMAGEWIDTH, width/2);
                output.SetField(TiffTag.IMAGELENGTH, height/2);
                output.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample);
                output.SetField(TiffTag.ROWSPERSTRIP, output.DefaultStripSize(0));
                output.SetField(TiffTag.PHOTOMETRIC, photo);
                output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);


                int c = 0;
                byte[][] holder = new byte[height][];

                for (int i = height/2; i < height; i++)
                //for (int j = 0; j < height/2 ; j++)
                {
                    holder[i] = buffer[i].Skip(buffer[i].Length/2).ToArray();

                    output.WriteScanline(holder[i], c);
                    c++;
                }
            }
        }

        System.Diagnostics.Process.Start("splitedImage.tif");

For other parts of the image, you can change the range of "i" in for loop.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!