13

I'm looking for a library that can open and copy sections of a large TIFF file. I've looked at LibTiff.Net which opens the file very quickly but it doesn't have any functions for cropping or copying sections of the image. My image is 100,000 x 100,000 pixels upwards and creating a System.Drawing.Bitmap of that size crashes the application so converting to a Bitmap first is not an option.

Can anyone recommend a .NET library?

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
JWood
  • 2,804
  • 2
  • 39
  • 64
  • Oh Lord, that's 40 *gigabytes*. I supposed you only have a 32-bit operating system to make it extra challenging? – Hans Passant Jan 25 '12 at 14:35
  • I'm running on 64-bit hardware but reading from the disk is going to be the ideal way of processing it. I'm looking deeper into LibTiff.Net which has functions to read scanline which may be what I need – JWood Jan 25 '12 at 14:41
  • Is the image color, grayscale or bilevel? For bilevel I have a native code solution that can solve the memory problem. Email me (bitbank@pobox.com). – BitBank Jan 25 '12 at 14:43
  • If you can preconvert it to PNG, this could help: http://code.google.com/p/pngcs/ – leonbloy Jan 25 '12 at 14:46
  • How hard would it be to extend the LibTiff.net code? Seems like most of the work has been done there. – RQDQ Jan 25 '12 at 16:27
  • 2
    Please answer my question. It makes a big difference if the 100kx100k images are color or bilevel. – BitBank Jan 26 '12 at 18:27

4 Answers4

6

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.

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
  • I've got a tiled image that is JPG compressed. I want to access the image and write it back out. Do I read with ReadEncodedTile and write with WriteTile or WriteEncodedTile? – Krip Feb 17 '12 at 14:28
  • I got it working with ReadEncodedTile followed by WriteEncodedTile. – Krip Feb 22 '12 at 15:11
5

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.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
0

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.

Nasser Tahani
  • 725
  • 12
  • 33
0

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)

plinth
  • 48,267
  • 11
  • 78
  • 120
  • Does it possible with dotImage to open TIFF files using a scale factor, let's say 1/2 or 1/4. So to quickly generate thumbnails for large TIFF files? How fast can I update metadata of large TIFF files? – Murat Korkmaz Feb 28 '14 at 07:23
  • This is not possible in the general case due to complications from tiling and image orientation. However, we do take most of these into consideration when implementing the IScaledDecoder interface to allow images to be read in scaled, so although the worst case doesn't change, the best cases are honored. As for updating metadata, what's fast to you? This is an IO bound process. It seems to work as well as I'd expect. – plinth Mar 06 '14 at 14:24
  • Please inform me when you'll add this capability. This is the only reason why I can switch from my current TIFF processing library to another one. – Murat Korkmaz Mar 06 '14 at 17:00
  • plinth, any news related to the IScaledDecoder interface implementation? – Murat Korkmaz May 29 '14 at 15:29