17

I'm looking to write custom metadata on to images(mostly jpegs, but could be others too). So far I haven't been able to do that through PIL preferably (I'm on centos 5 & I couldn't get pyexiv installed) I understand that I can update some pre-defined tags, but I need to create custom fields/tags! Can that be done?

This data would be created by users, so I wouldn't know what those tags are before hand or what they contain. I need to allow them to create tags/subtags & then write data for them. For example, someone may want to create this metadata on a particular image :

Category : Human

Physical :
    skin_type : smooth
    complexion : fair
    eye_color: blue
    beard: yes
    beard_color: brown
    age: mid

Location :
    city: london
    terrain: grass
    buildings: old

I also found that upon saving a jpeg through the PIL JpegImagePlugin, all previous metadata is overwritten with new data that you don't get to edit? Is that a bug?

Cheers, S

Saurabh
  • 451
  • 2
  • 4
  • 18

2 Answers2

26

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'}}
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • 2
    Many thanks for this! Actually, with pyexiv2, I can even write custom metadata: ` pyexiv2.xmp.register_namespace('/', 'custom') metadata['Xmp.custom.category'] = 'Human' ` But the problem is that on (centos 5 + python2.6), I'm not able to get pyexiv2 installed with all its dependencies :P So I'm trying to see if PIL works for me! – Saurabh Dec 23 '11 at 06:20
  • 1
    Thanks for showing how to make custom tags. Sorry I don't know much about CentOS (and I assume you've tried `yum install pyexiv2`.) Unfortunately, AFAIK, PIL 1.1.7 [can read but not write EXIF metadata](http://stackoverflow.com/a/1608545/190597) and [EXIF write support has not yet been added to PIL 1.2](https://bitbucket.org/effbot/pil-2009-raclette/src/cd403356263f/CHANGES). – unutbu Dec 23 '11 at 14:20
  • You are right. I'm giving up on PIL. But I've accepted your previous post as my answer as it gives me a fair ground to proceed on! Thanks! – Saurabh Dec 26 '11 at 04:56
  • pyexiv2 is now deprecated. see gexiv2 instead: https://wiki.gnome.org/Projects/gexiv2/PythonSupport – iacopo Apr 05 '17 at 08:52
  • 2
    For Python 3.x there's also [**py3exiv2**](http://www.py3exiv2.tuxfamily.org/) ([tutorial](http://python3-exiv2.readthedocs.io/en/latest/tutorial.html)). I had some problems installing it on my system (Ubutnu 16.04) and found out I first had to install the latest version of libexiv2-dev (`sudo apt-get install libexiv2-dev`), and only after this install py3exiv2 (`sudo -H pip3 install py3exiv2`) – sunyata Aug 05 '17 at 16:34
  • Very old answer but wondering if you know what library I could use to write alt tags to n number of images? Since the link above does not work anymore – Umar.H Apr 08 '19 at 18:03
  • 1
    @Datanovice: My experience with using python to modify exif data is outdated. Here are some ways you might find an answer however: (1) Search StackOverflow for [questions with both `python` and `exif` tags](https://stackoverflow.com/questions/tagged/exif+python), sort by "Newest", and see what libraries are being used. (2) A plain google search on "exif python3 write" pulls up interesting leads. (3) And you could [search pypi](https://pypi.org/search/?q=exif) for exif-related packages. – unutbu Apr 08 '19 at 18:37
  • 3
    These strategies seem to point toward [piexif](https://pypi.org/project/piexif/). – unutbu Apr 08 '19 at 18:40
  • If you got an error: `AttributeError: module 'pyexiv2' has no attribute 'ImageMetadata'`, then check this [answer](https://stackoverflow.com/a/65929248/15545196) – Ali Aug 31 '22 at 07:21
3

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.

Dewald Abrie
  • 1,392
  • 9
  • 21