LibTIFF: Extract all tags from a TIFF image
Asked Answered
N

6

8

I'm currently working on a project which requires me to split a TIFF image into a file containing all tags and a file containing all image data and to reconstruct a TIFF image from these files. The only problem is that it seems that LibTIFF provides no easy way to grab all tags from an image. I've tried using TIFFGetTagListCount and then TIFFGetField to retrieve the tag, but this only returns a small subset of the tags. I've started rolling my own version, but I just want to double check and make sure I'm not overlooking something as this seems like a pretty obvious feature that should be included in the library.

Nunes answered 15/12, 2009 at 2:21 Comment(1)
Out of curiosity, did you find a solution to this problem?Erich
I
6

Here is the closes you can get for scanning all tags:

 #include "LibTIFF/tif_dir.h"
 ...

 TIFFDirectory *td = &tif->tif_dir;

 for (int fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
    const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];

    // test if tag value is set
    // (lifted directly form LibTiff _TIFFWriteDirectory)

        if( fip->field_bit == FIELD_CUSTOM ) {
            int ci, is_set = FALSE;

            for( ci = 0; ci < td->td_customValueCount; ci++ )
                is_set |= (td->td_customValues[ci].info == fip);

            if( !is_set )
                continue;
        } else if(!TIFFFieldSet(tif, fip->field_bit))
            continue;

        // else: process the fip->field_tag


    }

Note that you will have to take into account that some tags will appear twice (LONG and SHORT version), but only one of these will have value. The correct type to use can be looked up in the included header (the TIFFDirectory struct).

There also other catches on how to read the tags, but this at least will make you loop over all of them (the standard ones). See tif_dirinfo.c for pointers if you get stuck.

Impeachment answered 2/7, 2010 at 16:28 Comment(3)
Well since tif_dir.h is an internal header (i.e. not exposed by the built library), including it in causes all sorts of problems like redefinitions, missing dependencies, etc. Any other way around this?Erich
@Anish Ramaswamy Not that I know of. As said, this is reverse-engineered from the LibTIFF source. If you have problems with redefinitions, try to isolate it in separate translation unit or a small library. As for missing decl. - other includes must be added as well. IIRC, only headers will do, no need to compile any .c from the lib.Impeachment
That just seems to be inelegant. I'm still on the hunt. Thanks!Erich
C
5

Printing all tags with tifffile:

from tifffile import TiffFile
for page in TiffFile(path_to_file).pages:
    for tag in page.tags.values():
        print(tag.name, tag.code, tag.dtype, tag.count, tag.value)
Counterfactual answered 15/12, 2009 at 6:22 Comment(2)
Also, tifffile.py doesn't seem to support LZW compressed tiff filesPorkpie
@Porkpie It does support them (and did even back in Oct 2018), but only if the optional dependency on imagecodecs is satisfied.Jacket
P
1

You can use tif_dir field of the image. It is a struct with at least the following fields:

  • td_customValueCount contains the number of 'custom' tag counts,
  • td_customValues is the list of td_customValueCount tag values (indexed from 0), and is of type TIFFTagValue *.

So you should be able to do something like this (in true fashion of online code, this is untested, of course!):

for (i=0; i < tiffimage->tif_dir->td_customValueCount; ++i) {
    const TIFFFieldInfo *info = tiffimage->tif_dir->td_customValues[i].info;
    const char *tagname = info->field_name();
    /* process tag */
}

See TIFFDirectory Struct Reference. Hope that helps.

Pu answered 15/12, 2009 at 2:50 Comment(0)
C
0

addingtags.html in the libtiff documentation contains information on handling non-standard tags (by default they're ignored). Could that be the problem?

Circumpolar answered 15/12, 2009 at 2:46 Comment(1)
Non-standard tags are not the issue actually, as simple standard tags like TIFF_IMAGEWIDTH and TIFF_IMAGELENGTH don't seem to be included in the tag list count. It's quite strange actually.Nunes
M
0

The tiffdump utility (which ships with libtiff) accomplishes this, but looking at the code, it looks like they're mostly working around the library. They actually call lseek and read to read the tag info.

Math answered 15/12, 2009 at 2:51 Comment(0)
S
0

Correcting issue with the for loop found in cgohlke's answer above. Also extending with a more complete script so is easier to run from the command-line.

import sys, getopt
from tifffile import TiffFile

def PrintAll(path_to_file):
    print('Tag.Name, Tag.Code, Tag.DType, Tag.Count, Tag.Value')
    for page in TiffFile(path_to_file).pages:
        for tag in page.tags.values():
            print(tag.name, tag.code, tag.dtype, tag.count, tag.value)

def main(argv):
    try:
        opts, args = getopt.getopt(argv, 'hi:v', ["help","image="])
    except getopt.GetoptError:
        print('Argv error')
        sys.exit(2)
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            print('printalltifftags.py -i c:\images\myimage.tif')
            sys.exit(0)
        elif opt in ('-i', '--image'):
            filePath = arg
    print('Image: ' + filePath)
    PrintAll(filePath)

if __name__ == '__main__':
    main(sys.argv[1:])
Southsouthwest answered 27/1, 2020 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.