3

How to load a part of a *.tif image without loading this image into memory.

I have to work with big TIFF files. (> 4 GB). I tried to read this file using BinaryReader, and using BitMiracle.LibTiff.Classic to convert bytes into image. But I didn't find example for how to read a specific pixel in a TIFF file.

Maybe be you have some solution for this task.

Lets say i have a BigScan.tif file and it is always:

Image Compression -  NONE
Pixel Order       -  Interleaved (RGBRGB)
Byte Order        -  IBM PC

I have some variable:

ImagePart with  User Defined Width
ImagePart with  User Define Height
ImagePArt with  User Defined Location

The question is, how could I get ImagePart from BigScan.tif?

But it would be best to have the ability to read information of the pixel in "BigScan.tif" with (x,y) coorinates.

I need to read a pixel from the BigScan.tif in specified place, with such function:

public Color GetPixelColorFromTiffImage(string TiffFileName, int PixelPositionX, int PixelPositionY)
{
    //Some Code
   return returnedColor;
}

Very strange but the support did`t unswer my quastion. May be somebody knows it. Why dose this part of the code from BitMiracle Samples wrote to 'raster' array numbers like "-11512229", "-11838376" and so on.

 using (Tiff image = Tiff.Open(fullImageLocation, "r"))
        {

            // Find the width and height of the image
            FieldValue[] value = image.GetField(TiffTag.IMAGEWIDTH);
             width = value[0].ToInt();

            value = image.GetField(TiffTag.IMAGELENGTH);
            height = value[0].ToInt();

            int imageSize = height * width;
            int[] raster = new int[imageSize];


            // Read the image into the memory buffer
            if (!image.ReadRGBAImage(width, height, raster))
            {
                MessageBox.Show("Could not read image");

            }


            using (Bitmap btm = new Bitmap(200, 200))
            {
                for (int i = 0; i < btm.Width; ++i)
                    for (int j = 0; j < btm.Height; ++j)
                        btm.SetPixel(i, j, getSample(i + 330, j + 30, raster, width, height));

                ReternedBitmap = btm;
            }
        }//using    
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Alexey Gapon
  • 73
  • 2
  • 11
  • 1
    Does this help? http://bitmiracle.com/libtiff/help/how-to-read-tiff-scanlines-in-a-random-fashion.aspx – Roger Rowland Apr 30 '13 at 09:32
  • Well i saw this page. But i am still wondering how it can help. How, using this, possible to set the position of the pixel, and read it data from the main tif file? – Alexey Gapon Apr 30 '13 at 10:56
  • 1
    It allows you to read any number of scalines from the image - so you can at least choose a range of rows (y coordinate), even if you have to take the full width (x coordinate) - maybe this helps? – Roger Rowland Apr 30 '13 at 11:22
  • Sorry i still do not understand. Can you write an example using readScinline, how can i get pixel info with coordinates (x,y)? – Alexey Gapon Apr 30 '13 at 11:26
  • I have 219 000 pix in width. I can`t load all this data just for 1 pixel. – Alexey Gapon Apr 30 '13 at 13:08
  • 1
    Well, it's not ideal, but it's better than having to load the whole image ;-) I don't know of a single-pixel accessor for TIFF because of the line-based compression options. – Roger Rowland Apr 30 '13 at 13:13
  • No it will use to much memory. So will write my own reader. Thank you for your advices. – Alexey Gapon Apr 30 '13 at 13:48
  • According to documentation for Tiff.ReadRGBAImage method, Raster pixels are 8-bit packed red, green, blue, alpha samples. The GetR(Int32), GetG(Int32), GetB(Int32), and GetA(Int32) should be used to access individual samples. – Bobrovsky May 03 '13 at 18:15

1 Answers1

0

Your question is unclear (you ask at least two different questions).

If you need to crop a part of a larger image then you need to:

  1. read each relevant scanline of a source image
  2. copy part of that scanline to a new image.

If you need to get color value of a single pixel in a given location than again you need to:

  1. read relevant scanline
  2. find relevant bytes in that scanline
  3. pack those bytes into a Color structure or whatever else

You didn't specify what are Photometric, BitsPerSample and SamplesPerPixel values for your image, so it's hard to tell what exactly are you dealing with.

Most probably, you are faced with geo-images. If so, they are probably RGB, 24bit, tiled images.

For tiled images it is possible to read only small part (say, 256 x 256 pixels) of the image at once. But even if they are stripped, one scanline of such an image will take only about 1 MB of memory (219 000 pixels * 3 bytes per pixel). It's nothing if you are really need to process such big images.

I wouldn't recommend you to try developing your own parser. It's not that easy if you know only basics about TIFF format.

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
  • Thank you very much for your answer. You are right, now I have some problems with writing my own "opener" because as is turned out - I don`t actualy know the specify of the files ((. I just hope that BitMiracle will help. Could you help me to write a part of the code? Because it is real magic for me with *.tiff files. – Alexey Gapon May 01 '13 at 22:18