1

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?

LA_
  • 19,823
  • 58
  • 172
  • 308

1 Answers1

4

UPDATED POST 06-12-2022

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
----------------------------------------

ORIGINAL POST 06-11-2022

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.

Life is complex
  • 15,374
  • 5
  • 29
  • 58
  • Thanks! But I can read the metadata from the HEIF file. The question is how to decode it. I don't want to wait for file conversion to JPG. – LA_ Jun 11 '22 at 16:24
  • @LA_. I overlooked that section of the question. Are you getting any keys or values for this `GPSTAGS.items()`? – Life is complex Jun 11 '22 at 21:58