-
Star
(104)
You must be signed in to star a gist -
Fork
(53)
You must be signed in to fork a gist
-
-
Save erans/983821 to your computer and use it in GitHub Desktop.
from PIL import Image | |
from PIL.ExifTags import TAGS, GPSTAGS | |
def get_exif_data(image): | |
"""Returns a dictionary from the exif data of an PIL Image item. Also converts the GPS Tags""" | |
exif_data = {} | |
info = image._getexif() | |
if info: | |
for tag, value in info.items(): | |
decoded = TAGS.get(tag, tag) | |
if decoded == "GPSInfo": | |
gps_data = {} | |
for t in value: | |
sub_decoded = GPSTAGS.get(t, t) | |
gps_data[sub_decoded] = value[t] | |
exif_data[decoded] = gps_data | |
else: | |
exif_data[decoded] = value | |
return exif_data | |
def _get_if_exist(data, key): | |
if key in data: | |
return data[key] | |
return None | |
def _convert_to_degress(value): | |
"""Helper function to convert the GPS coordinates stored in the EXIF to degress in float format""" | |
d0 = value[0][0] | |
d1 = value[0][1] | |
d = float(d0) / float(d1) | |
m0 = value[1][0] | |
m1 = value[1][1] | |
m = float(m0) / float(m1) | |
s0 = value[2][0] | |
s1 = value[2][1] | |
s = float(s0) / float(s1) | |
return d + (m / 60.0) + (s / 3600.0) | |
def get_lat_lon(exif_data): | |
"""Returns the latitude and longitude, if available, from the provided exif_data (obtained through get_exif_data above)""" | |
lat = None | |
lon = None | |
if "GPSInfo" in exif_data: | |
gps_info = exif_data["GPSInfo"] | |
gps_latitude = _get_if_exist(gps_info, "GPSLatitude") | |
gps_latitude_ref = _get_if_exist(gps_info, 'GPSLatitudeRef') | |
gps_longitude = _get_if_exist(gps_info, 'GPSLongitude') | |
gps_longitude_ref = _get_if_exist(gps_info, 'GPSLongitudeRef') | |
if gps_latitude and gps_latitude_ref and gps_longitude and gps_longitude_ref: | |
lat = _convert_to_degress(gps_latitude) | |
if gps_latitude_ref != "N": | |
lat = 0 - lat | |
lon = _convert_to_degress(gps_longitude) | |
if gps_longitude_ref != "E": | |
lon = 0 - lon | |
return lat, lon | |
################ | |
# Example ###### | |
################ | |
if __name__ == "__main__": | |
image = ... # load an image through PIL's Image object | |
exif_data = get_exif_data(image) | |
print get_lat_lon(exif_data) |
The _getexif attribute may not exist if you've opened a PNG or GIF file. The following might be a better alternative to line 7:
info = getattr(image, '_getexif', lambda: None)()
lines 23-27:
you can replace by:
return data.get(key, None)
@DieselDraft: Or just data.get(key)
I forked this (and made some minor changes): https://gist.github.com/moshekaplan/5330395
@erans: What is the licensing status of this piece of code? I am currently adding EXIF support to a static photo gallery generator and one of the requested features is of course support for geotagged photos. Now, that you (and the others) have done everything that's necessary for that, I would like to integrate that. But without any written permission it's just not possible.
@matze I will add licensing later today but it's basically MIT do whatever you want just add attribution :-)
Thanks for the clarification. You will be of course properly attributed and credited!
Thanks. This helped me a lot even though I'm using exifread. If someone is curious, here is version of _convert_to_degress
when using exifread:
def _convert_to_degress(value):
deg = value[0]
deg = float(deg.num) / float(deg.den)
minute = value[1]
minute = float(minute.num) / float(minute.den)
sec = value[2]
sec = float(sec.num) / float(sec.den)
return deg + (minute / 60.0) + (sec / 3600.0)
Pillow currently has a bug with GPS EXIF information (as of version 3.0.0): python-pillow/Pillow#1477.
Downgraded to 2.9.0 can be used as a temporary workaround.
I created a fork that accepts a list of images as input and prints the GPS lat, lon, altitude, heading, speed and timestamp values in a TSV fromat: https://gist.github.com/valgur/2fbed04680864fab1bfc
how can i use it to process the images on my django server
you can do much shorter and clearer, see my gist in 25 lines of code : https://gist.github.com/maxbellec/dbb60d136565e3c4b805931f5aad2c6d
This was super useful, thank you.
line 74
image = Image.open("image.jpg")
Great piece of code
As now from PIL 7.0.0 the GPS data are stored in IFDRational, how do you get values of its numerator and denominator?
>>> f.denominator
<property object at 0x7f44e320a130>
@step135 - GPS data can be found at get_ifd(0x8825)
using Pillow
.
This is what I do...
def get_exif(image):
data = dict()
exif = image.getexif()
if exif:
# Basic exif (camera make/model, etc)
for key, val in exif.items():
data[ExifTags.TAGS[key]] = val
# Aperture, shutter, flash, lens, tz offset, etc
ifd = exif.get_ifd(0x8769)
for key, val in ifd.items():
data[ExifTags.TAGS[key]] = val
# GPS Info
ifd = exif.get_ifd(0x8825)
for key, val in ifd.items():
data[ExifTags.GPSTAGS[key]] = val
return data
It's good to know things are much better than they were back in 2011 :)
Lines 17-19 need to be right indented one level right.