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.
You can make use of extended file attributes which is a filesystem feature that do just what you want: store custom metadata along files. In Python, this is implemented by the os module through setxattr() and getxattr() functions.
The use of embedded IPTC tags in image file formats became widespread with the use of the Adobe Photoshop tool for image editing. IPTC metadata can be stored in TIFF and JPEG format images. interMedia supports the extraction of IPTC metadata from TIFF and JPEG file formats.
To read the metadata from the images, we can use the piexif library: To extract the data, we call the function piexif.load with image we want to know the values: This function returns a dictionary containing the following keys: “0th”, “Exif”, “GPS”, “1st”, “Interop”, and “thumbnail”.
Metadata stands for data about data. In case of images, metadata means details about the image and its production. Some metadata is generated automatically by the capturing device.
Python has PIL library which makes the task of extracting metadata from an image extremely easy that too by using just a few lines. Approach: Import the pillow module. Load the image; Get the metadata. The metadata so obtained; Convert it into human-readable form. There are many types of metadata but in this we are only focusing on Exif metadata
Step 1: Importing modules. Step 2: Load the image and extract the exif data. Step 3: Convert the exif tag id (denoted by tagid in the code ) into human readable form denoted by tagname in the code and getting its respective value. Application to extract Metadata from a image with pillow : below script implements the above approach Attention geek!
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With