3

Is there a way to find the size (in bytes) of the header information in a GeoTIFF file using Python? I am not trying to read the header (I know I can use gdalinfo for this) but rather to figure out what position I need to skip to in order to read the file as binary. This is because I am interested in testing numpy memory-mapped arrays for reading portions of an image from the disk. I would like to test this versus the gdal builtin ReadAsArray() method because I enjoy the flexibility of numpy indexing.

  • 5
    TIFF is a complex beastie. You will have a lot a work ahead of you to handle different interleaving, compression, tiling, tiff format, internal non-header data such as overviews and masks, multi-pages, etc. – user2856 Aug 20 '18 at 0:16
  • 1
    There is nothing GIS specific in reading GeoTIFFs but I think that first you should read fileformat.info/format/tiff/corion.htm, then the offset to the first IFD, and find StripOffsets from there This field is the only way for a reader to find the image data. In general case you can't just jump to one offset value and start reading the data because strips may not be continuous. But StripOffsets should give a complete list of offsets for you. – user30184 Aug 20 '18 at 6:24
  • Or you could gdal_translate to ENVI or EHdr format to output a flat binary file + sidecar header. – user2856 Aug 20 '18 at 7:13
  • Use rasterio, it gives you numpy arrays: rasterio.readthedocs.io – bugmenot123 Aug 20 '18 at 8:49
  • @user30184 thanks for the tips & reference material, this looks very useful. I hadn't been able to find this sort of documentation so far but it might be exactly what I need. – corvus Aug 20 '18 at 13:48
1

Check out tifffile (GitHub mirror), which is a Python package to read and write image data from and to TIFF files.

import tifffile
import numpy as np

fname = 'my.tif'
tif = tifffile.TiffFile(fname)
page = tif.pages[0]  # first page
arr = page.asarray()  # we're done

So far, this is no different than either rasterio or GDAL.

To answer your question, you can get the byte offset and size from the page.is_contiguous property, then read it with regular numpy or any other tool that can read contiguous data:

offset, byte_count = page.is_contiguous
with open(fname, 'rb') as fp:
    fp.seek(offset)
    # if this is a 4-byte float file ...
    arr2 = np.fromfile(fp, dtype=np.float32, count=byte_count / 4)
arr2.shape = arr.shape
assert (arr2 == arr).all()
  • Thanks! In the end I think I may go with built-in gdal functions as I have just discovered the gdal.Dataset.GetVirtualMemArray method which seems to do exactly what I was ultimately hoping to do, & saves me the trouble of worrying about the internal file structure. But, it is good to know about the tifffile package & this does exactly what I asked for, so +1. In addition this may be very handy for anyone who has a specific need for this functionality. – corvus Aug 23 '18 at 23:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.