Dims
Dims

Reputation: 51039

How to write CUSTOM metadata into JPEG with Python?

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.

Upvotes: 14

Views: 17954

Answers (2)

Status
Status

Reputation: 940

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

Upvotes: 10

ladorm
ladorm

Reputation: 606

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.

Upvotes: 7

Related Questions