13

How to write CUSTOM metadata into JPEG with Python?

I tried

import piexif
exif_dict = {
                'uwi': myvalue1,
                'activity_type': myvalue2,
                'prediction': myvalue3,
                'url_current': myvalue4,
                'url_previous': mavalue5
            }
exif_bytes = piexif.dump(exif_dict)
with open(filename, "w") as fp:
    test_image.save(fp, "JPEG", exif=exif_bytes)

but see nothing in images with XnView. What am I doing wrong?

P.S. I don't need to write camera model, exposure and other stuff. I want to write my own custom metadata.

Dims
  • 47,675
  • 117
  • 331
  • 600
  • Does this answer your question? [How to modify EXIF data in python](https://stackoverflow.com/questions/44636152/how-to-modify-exif-data-in-python) – Tabish Mir May 12 '20 at 11:45

3 Answers3

11

I can’t find a clear answer about custom tags (these links suggest you can with a third party tool), but looking at the specifications gives only the defined tags so I’m going to say no, you can’t make your own metadata tags, at least not directly.


So what you can do is write your own data to any of the defined tags. It’s best to use the MakerNote tag for this - most camera makers store their own custom metadata there. Dump your custom flags into a byte string before stuffing it into the MakerNote tag:

from PIL import Image
import piexif
import pickle

tags = {'url_current'   : 'https://stackoverflow.com/q/52729428/1846249',
        'contains_fish' : False,
        3               : 0.14159265358979323, }

data = pickle.dumps(tags)
exif_ifd = {piexif.ExifIFD.MakerNote: data}

exif_dict = {"0th": {}, "Exif": exif_ifd, "1st": {},
             "thumbnail": None, "GPS": {}}

img = Image.new('RGB', (500, 500), 'green')
exif_dat = piexif.dump(exif_dict)
img.save('image.jpg',  exif=exif_dat)

Because it's your own format, you'll need to read it back out yourself:

img = Image.open('image.jpg')
raw = img.getexif()[piexif.ExifIFD.MakerNote]
tags = pickle.loads(raw)

exiftool will see the image has a MakerNote, but won't recognize it:

C:\> exiftool image.jpg -MakerNote
Warning: [minor] Unrecognized MakerNotes - image.jpg

You could also store it in the UserComment tag - storing is done in the same way.

C:\>exiftool image.jpg -UserComment
User Comment                    : Ç.ò^}ö(î.url_currentöî,https://stackoverflow.com/q/52729428/1846249öî.contains_fishöëK.G?┬.╡DB╤äu.

P.S. there's a limit of 64kB for metadata in jpeg images

Status
  • 912
  • 1
  • 12
  • 23
  • I get a key error in img.getexif()[[piexif.ExifIFD.MakerNote]], the maker note is an int that does not exist in img.getexif if I transform it into a dictionary – Ricardo Guerreiro Sep 08 '22 at 08:33
8

Check out the docs on how to use piexif. What you are doing wrong for example is trying to write custom metadata and opening the file with open instead of opening with Image from the PIL module.

Cutting down the example from the docs, you could do something like this:

from PIL import Image
import piexif

zeroth_ifd = {
              piexif.ImageIFD.Make: u"Canon",
              piexif.ImageIFD.XResolution: (96, 1),
              piexif.ImageIFD.YResolution: (96, 1),
              piexif.ImageIFD.Software: u"piexif"
              }
exif_ifd = {
            piexif.ExifIFD.DateTimeOriginal: u"2099:09:29 10:10:10",
            piexif.ExifIFD.LensMake: u"LensMake",
            piexif.ExifIFD.Sharpness: 65535,
            piexif.ExifIFD.LensSpecification: ((1, 1), (1, 1), (1, 1), (1, 1)),
            }
gps_ifd = {
           piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
           piexif.GPSIFD.GPSAltitudeRef: 1,
           piexif.GPSIFD.GPSDateStamp: u"1999:99:99 99:99:99",
           }
first_ifd = {
             piexif.ImageIFD.Make: u"Canon",
             piexif.ImageIFD.XResolution: (40, 1),
             piexif.ImageIFD.YResolution: (40, 1),
             piexif.ImageIFD.Software: u"piexif"
             }

exif_dict = {"0th":zeroth_ifd, "Exif":exif_ifd, "GPS":gps_ifd, "1st":first_ifd, "thumbnail":thumbnail}
exif_bytes = piexif.dump(exif_dict)
im = Image.open("foo.jpg")
im.save("out.jpg", exif=exif_bytes)

You can check all the metadata fields that you can edit with piexif here.

ladorm
  • 588
  • 5
  • 11
  • 4
    But is it possible to save custom metadata in JPEG? I don't want to save camera model etc, it is unneeded for me. – Dims Oct 10 '18 at 07:42
  • Also I am not opening existing image, I am creating my own one. – Dims Oct 10 '18 at 07:43
  • 1
    Original poster emphasized he wished to add *custom* attributes. The example given is helpful, but, it explicitly references only EXIF standard attributes. – MikeMontana Nov 30 '21 at 18:23
0

I don't know Python, but the marker FF E0-EF (excluded maybe, althouth not mandatory, E1 for exif) it's precisely used for applications. I've just included a jpeg file (to use custom thumbnail formats) with the marker FFE2 and the Jpeg can be read normally.