I use the following code to extract GPS location both from JPG and HEIC files:
#coding=utf-8
from PIL import Image
from urllib.request import urlopen
from PIL.ExifTags import TAGS
from PIL.ExifTags import GPSTAGS
from pillow_heif import register_heif_opener
def get_exif(filename):
image = Image.open(filename)
image.verify()
return image._getexif()
def get_geotagging(exif):
if not exif:
raise ValueError("No EXIF metadata found")
geotagging = {}
for (idx, tag) in TAGS.items():
if tag == 'GPSInfo':
if idx not in exif:
raise ValueError("No EXIF geotagging found")
for (key, val) in GPSTAGS.items():
if key in exif[idx]:
geotagging[val] = exif[idx][key]
return geotagging
register_heif_opener()
my_image='IMG_9610.HEIC'
#my_image='IMG_20210116_215317.jpg'
exif = get_exif(my_image)
labeled = get_geotagging(exif)
print(labeled)
This code works well with JPEG files, but returns the following error with HEIC:
AttributeError: _getexif
If I add the following function
def get_labeled_exif(exif):
labeled = {}
for (key, val) in exif.items():
labeled[TAGS.get(key)] = val
return labeled
and replace '_getexif()' with 'getexif()' then it works for both files, but the data is encrypted there - 'GPSInfo': 1234 and get_geotagging() doesn't work for such exif.
How could I fix it?
The code below is able to extract the GEO tagging information from a HEIC image file on my system.
from PIL import Image
from pillow_heif import register_heif_opener
def get_exif(filename):
image = Image.open(filename)
image.verify()
return image.getexif().get_ifd(0x8825)
def get_geotagging(exif):
geo_tagging_info = {}
if not exif:
raise ValueError("No EXIF metadata found")
else:
gps_keys = ['GPSVersionID', 'GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude',
'GPSAltitudeRef', 'GPSAltitude', 'GPSTimeStamp', 'GPSSatellites', 'GPSStatus', 'GPSMeasureMode',
'GPSDOP', 'GPSSpeedRef', 'GPSSpeed', 'GPSTrackRef', 'GPSTrack', 'GPSImgDirectionRef',
'GPSImgDirection', 'GPSMapDatum', 'GPSDestLatitudeRef', 'GPSDestLatitude', 'GPSDestLongitudeRef',
'GPSDestLongitude', 'GPSDestBearingRef', 'GPSDestBearing', 'GPSDestDistanceRef', 'GPSDestDistance',
'GPSProcessingMethod', 'GPSAreaInformation', 'GPSDateStamp', 'GPSDifferential']
for k, v in exif.items():
try:
geo_tagging_info[gps_keys[k]] = str(v)
except IndexError:
pass
return geo_tagging_info
register_heif_opener()
my_image = 'IMG_8362.heic'
image_info = get_exif(my_image)
results = get_geotagging(image_info)
print(results)
# x used to mask data
{'GPSLatitudeRef': 'N',
'GPSLatitude': '(3x.0, 5x.0, 1x.0x)',
'GPSLongitudeRef': 'W',
'GPSLongitude': '(8x.0, 2x.0, 5x.2x)',
'GPSAltitudeRef': "b'\\x00'",
'GPSAltitude': '279.63243243243244',
'GPSSpeedRef': 'K',
'GPSSpeed': '0.04649941997239198',
'GPSImgDirectionRef': 'T',
'GPSImgDirection': '274.37165833514456',
'GPSDestBearingRef': 'T',
'GPSDestBearing': '27x.37165833514456',
'GPSDateStamp': '2022:06:12'}
----------------------------------------
My system information
----------------------------------------
Platform: Apple
OS Version: macOS Catalina 10.15.7
Python: 3.9
Pillow: 9.1.1
pillow_heif: 0.3.0
----------------------------------------
The short answer is that Pillow does not currently support the High Efficiency Image Format (HEIF) file format.
Reference:
One of the workarounds for this issue is pyheif. This Python package has the functionality to covert a HEIC image to a JPEG one. After this transformation Pillow will be able to read the data from the image.
Another workaround for this format reading problem is piexif. Here is an answer that I posted on converting a TIFF file to a JPEG one for reading with Pillow.
You could also use ExifTool, which reads HEIC files out of the box. Using it is slightly more complicated, because it requires using subprocess.
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