Writing complex custom metadata on images through python

You might have an easier time installing the piexif package and save your custom data to the ExifIFD.UserComment field.

Sample data:

userdata = {
    'Category': 'Human',
    'Physical': {
        'skin_type': 'smooth',
        'complexion': 'fair'
    },
    'Location': {
        'city': 'london'
    }
}

Encoding data into image:

import json
import piexif
import piexif.helper

# %% Write out exif data
# load existing exif data from image
exif_dict = piexif.load(filename)
# insert custom data in usercomment field
exif_dict["Exif"][piexif.ExifIFD.UserComment] = piexif.helper.UserComment.dump(
    json.dumps(userdata),
    encoding="unicode"
)
# insert mutated data (serialised into JSON) into image
piexif.insert(
    piexif.dump(exif_dict),
    filename
)

Decoding data from image:

# %% Read in exif data
exif_dict = piexif.load(filename)
# Extract the serialized data
user_comment = piexif.helper.UserComment.load(exif_dict["Exif"][piexif.ExifIFD.UserComment])
# Deserialize
d = json.loads(user_comment)
print("Read in exif data: %s" % d)

Note that only JPEG and WebP and TIFF is supported.


The python pyexiv2 module can read/write metadata.

I think there is a limited set of valid EXIF tags. I don't know how, or if it is possible to create your own custom tags. However, you could use the Exif.Photo.UserComment tag, and fill it with JSON:

import pyexiv2
import json

metadata = pyexiv2.ImageMetadata(filename)
metadata.read()
userdata={'Category':'Human',
          'Physical': {
              'skin_type':'smooth',
              'complexion':'fair'
              },
          'Location': {
              'city': 'london'
              }
          }
metadata['Exif.Photo.UserComment']=json.dumps(userdata)
metadata.write()

And to read it back:

import pprint
filename='/tmp/image.jpg'
metadata = pyexiv2.ImageMetadata(filename)
metadata.read()
userdata=json.loads(metadata['Exif.Photo.UserComment'].value)
pprint.pprint(userdata)

yields

{u'Category': u'Human',
 u'Location': {u'city': u'london'},
 u'Physical': {u'complexion': u'fair', u'skin_type': u'smooth'}}