pythonimage-processingmetadatatifffiji

How to save ImageJ tiff metadata using Python


I'm trying to save a tiff stack using tifffile and using this solution to add ImageJ tiff metadata tags and values.

The code runs with no errors, but when I open "image info" in ImageJ, I don't see the new tag I created.

I don't really know how Tiff tags work, so I chose a tag called "Name" because this tag name exists when I open metadata that was saved with ImageJ.

I've only changed the function from the original solution a little bit to support my tag. This is the code I'm using:

def imagej_metadata_tags(metadata, byteorder):
    """Return IJMetadata and IJMetadataByteCounts tags from metadata dict.

    The tags can be passed to the TiffWriter.save function as extratags.

    """
    header = [{'>': b'IJIJ', '<': b'JIJI'}[byteorder]]
    bytecounts = [0]
    body = []

    def writestring(data, byteorder):
        return data.encode('utf-16' + {'>': 'be', '<': 'le'}[byteorder])

    def writedoubles(data, byteorder):
        return struct.pack(byteorder+('d' * len(data)), *data)

    def writebytes(data, byteorder):
        return data.tobytes()

    metadata_types = [
        ('Name', b'Name', 1, writestring),
    ]

    for key, mtype, count, func in metadata_types:
        if key not in metadata:
            continue
        if byteorder == '<':
            mtype = mtype[::-1]
        values = metadata[key]
        if count is None:
            count = len(values)
        else:
            values = [values]
        header.append(mtype + struct.pack(byteorder+'I', count))
        for value in values:
            data = func(value, byteorder)
            body.append(data)
            bytecounts.append(len(data))

    body = b''.join(body)
    header = b''.join(header)
    data = header + body
    bytecounts[0] = len(header)
    bytecounts = struct.pack(byteorder+('I' * len(bytecounts)), *bytecounts)
    return ((50839, 'B', len(data), data, True),
            (50838, 'I', len(bytecounts)//4, bytecounts, True))

ijtags = imagej_metadata_tags({'Name': 'DPY'}, '>')

tif.imsave(some_path, frame, imagej=True, extratags=ijtags)

Solution

  • The IJMetadata tag can only contain certain application specific information. See the doctring of the imagej_metadata_tag function. You can specify metadata={'Name': 'A name'} to save additional metadata in the ImageDescription tag. ImageJ may or may not use this information. The TIFF tags used by ImageJ are not documented.