5

I've already learnt how to read EXIF and XMP data's from JPG. Now I would like to write from value in attribute table into their XMP and EXIF tags.

This code Import EXIF / XMP , and I would like to do the opposite.

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from xml.etree import ElementTree as ET

layer = iface.activeLayer()
dpr = layer.dataProvider()

layer.startEditing()
apr_ind = layer.fields().indexFromName("apr")
exp_ind  = layer.fields().indexFromName("exp")
fyd_ind = layer.fields().indexFromName("fyd")

for feature in layer.getFeatures():
    file_path = feature["photo"] 
    print(file_path)
    img = Image.open(file_path)
    exif = { TAGS[k]: v for k, v in img._getexif().items() if k in TAGS }
    with open(file_path, "rb") as f:
        s = str(f.read())
    start = s.find('<x:xmpmeta')
    end   = s.find('</x:xmpmeta')
    xmp   = s[start:end+12].replace("\\n","\n")
    tree  = ET.XML(xmp)
    apr = exif["FNumber"][0]/exif["FNumber"][1]
    exp = exif["ExposureBiasValue"][0]
    fyd = tree[0][0].attrib['{http://www.dji.com/drone-dji/1.0/}GimbalPitchDegree']

    dpr.changeAttributeValues({ feature.id():{apr_ind: apr,
                                            exp_ind: exp }})
layer.commitChanges()
print("COMPLETED") 
0

2 Answers 2

5

pyexiv2 Solution:

Select layer and run the script. You have to change values to string for non-string fields using str() method. This solution is about layers which were created by ImportPhotos plugin. For other layers, you must specify the file path related to feature.

from pyexiv2 import Image

layer = iface.activeLayer()

for feature in layer.getFeatures():
    image = Image(feature["Path"]) # or Image("full_path_of_file_related_to_the_feature")
    metadata = image.read_all()

    metadata["EXIF"]["Exif.Image.Make"] = feature["Camera Mak"]
    metadata["XMP"]["Xmp.drone-dji.FlightYawDegree"] = str(feature["fyd"])
    metadata["XMP"]["Xmp.drone-dji.GimbalYawDegree"] = str(feature["gyd"])

    image.modify_all(metadata) # write new values to image file
6
  • I get this error: ModuleNotFoundError: No module named 'pyexiv2', how can I solve it?
    – zlikotp
    Dec 21, 2019 at 20:40
  • 2
    You should install it. pypi.org/project/pyexiv2 Dec 21, 2019 at 20:45
  • I've installed pyexiv2: C:\Windows\System32>python -m pip install pyexiv2 Requirement already satisfied: pyexiv2 in c:\progra~1\qgis3~1.10\apps\python37\lib\site-packages (1.3.0) but I still get an error after running the script : OSError: [WinError 127] La procédure spécifiée est introuvable
    – zlikotp
    Dec 21, 2019 at 21:48
  • Is pyexiv2 working in python 3.7 ? this solution doesn't work for me because I can't use pyexiv2 module. Is there another solution using PIL ?
    – zlikotp
    Dec 22, 2019 at 20:20
  • 1
    I use QGIS 3.4 (installed by OSGeo4W Network Installer), Windows 10 64bit, Python 3.7. I couldn't install for QGISes installed by standalone installer, too. Dec 23, 2019 at 6:48
1

I usually use pyexiv2 to set exif information in JPG files, but when I import the library in a script QGIS script crash.

I found a solution using the library exif:

https://pypi.org/project/exif/

It's so easy to use, and with Qgis I don,'t have any problem.

In this code I insert GPS coordinates to a snapshot of screen:

from exif import Image
with open(file_name, 'rb') as image_file:
    my_image = Image(image_file)

my_image.make = "Python"
my_image.gps_latitude_ref=exif_lat_ref
my_image.gps_latitude=exif_lat
my_image.gps_longitude_ref= exif_lon_ref
my_image.gps_longitude= exif_lon

with open(file_name, 'wb') as new_image_file:
    new_image_file.write(my_image.get_file())

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.