3

I need to add arbitrary data to a JPEG image. Specifically, I need to store two integers. From reading about EXIF data, I'm under the impression that it is not possible to make your own custom fields, but rather the EXIF standard fields must be used.

This post Custom Exif Tags however mentions a UserComment field which I gather it is possible to write a string to. If this is the only option it's fine since I can store two integers in a comma-delimited string, ex '2,5' to store the integers 2 and 5, so if I only have one string of storage to work with it's still sufficient.

I downloaded a few random images from a Google image search and found they don't seem to have EXIF data, perhaps it's stripped off purposefully by Google? Also I took a few images with my cell phone and found that as expected they have a significant amount of EXIF data (image size, GPS location, etc.)

Upon some Googleing I found this example on how to read/dump EXIF data:

from PIL import Image

image = Image.open('image.jpg')
exifData = image._getexif()
print('exifData = ' + str(exifData))

This works great, if I run this on an image with no EXIF data I get:

exifData = None

and if I run this on an image with EXIF data I get a dictionary showing the EXIF fields as expected.

Now my question is, how can I add to the EXIF data? Using the UserComment 37510 field mentioned in the above linked post, and also here https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/usercomment.html, and using piexif this is my best attempt so far:

from PIL import Image
import piexif

image = Image.open('image.jpg')

exifData = image._getexif()

if exifData is None:
    exifData = {}
# end if

exifData[37510] = 'my message'

exifDataBytes = piexif.dump(exifData)

image.save('image_mod.jpg', format='jpeg', exif=exifDataBytes)

If I then run the 1st code above on image_mod.jpg I get:

exifData = {}

So clearly the 37510 message was not properly written. I get this same empty dictionary result whether I'm using an image that has EXIF data or an image without EXIF data to begin with.

Before somebody marks this as a duplicate, I also tried what this post How can I insert EXIF/other metadata into a JPEG stored in a memory buffer? mentions in the highest-rated answer and got the same result when attempting to read the EXIF data (empty dictionary).

What am I doing wrong? How can I properly add custom EXIF data to an image using 37510, or any other means?

cdahms
  • 3,402
  • 10
  • 49
  • 75

2 Answers2

5

You're missing a step in handling the data passed to piexif.dump:

exif_ifd = {piexif.ExifIFD.UserComment: 'my message'.encode()}

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

exif_dat = piexif.dump(exif_dict)
img.save('image_mod.jpg',  exif=exif_dat)

You should be able to read it back out after this. See also this answer for dealing with custom metadata.

Louis Maddox
  • 5,226
  • 5
  • 36
  • 66
Status
  • 912
  • 1
  • 12
  • 23
2

Rasterio tags are the easiest way to add metadata of any kind to an image. Easy and practical. example:

import rasterio

old_file=rasterio.open('old_image.tif')
profile=old_file.profile
data=old_file.read()


with rasterio.open('new_image.tif','w',**profile) as dst:
        dst.update_tags(a='1', b='2')
        dst.write(data)
        dst.close() 

#now access the tags like below:

im=rasterio.open('new_image.tif')
print(im.tags())
H.J.Biglu
  • 21
  • 2