def GetMetaData(image, printAll = False): ''' Get metadata dic from a JPG image... the image is open by PIL.Image... ''' from PIL.ExifTags import TAGS, GPSTAGS if isinstance(image, str): image = Image.open(image) _TAGS_r = dict(((v, k) for k, v in TAGS.items())) _GPSTAGS_r = dict(((v, k) for k, v in GPSTAGS.items())) exifd = image._getexif() if hasattr(image, '_getexif') else image.tag keys = list(exifd.keys()) if _TAGS_r["MakerNote"] in keys: keys.remove(_TAGS_r["MakerNote"]) if _TAGS_r["UserComment"] in keys: keys.remove(_TAGS_r["UserComment"]) keys = [k for k in keys if k in TAGS] if printAll: print '################ Medatada:' print("\n".join([str((TAGS[k], exifd[k]))for k in keys])) iget = lambda x : exifd[_TAGS_r[x]] isk = lambda x : _TAGS_r[x] in keys outdic = {} if isk('ExposureTime'): n,d = iget("ExposureTime") exptime = float(n)/d outdic['EXPTIME'] = exptime if isk('DateTimeOriginal'): outdic['DATE-OBS'] = str(iget('DateTimeOriginal')) elif isk('DateTime'): outdic['DATE-OBS'] = str(iget('DateTime')) if isk('Make') and isk('Model'): outdic['INSTRUME'] = '%s - %s'%(str(iget('Make')), str(iget('Model'))) return outdic
def rotationFromExifTag(imgPath): TAGSinverted = {v: k for k, v in TAGS.items()} orientationExifId = TAGSinverted['Orientation'] try: imageExifTags = Image.open(imgPath)._getexif() except: imageExifTags = None # rotate the image if orientation exif tag is present rotation = 0 if imageExifTags != None and orientationExifId != None and orientationExifId in imageExifTags: orientation = imageExifTags[orientationExifId] # print ("orientation = " + str(imageExifTags[orientationExifId])) if orientation == 1 or orientation == 0: rotation = 0 # no need to do anything elif orientation == 3: rotation = 0 elif orientation == 6: rotation = -90 elif orientation == 8: rotation = 90 else: print("ERROR: orientation = " + str(orientation) + " not_supported!") raise Exception("ERROR: orientation = " + str(orientation) + " not_supported!") return rotation
def get_coordinates(self): """Get latitude and longitude from geo tags :param self: :return: latitude and longitude """ if not self.exif: raise ValueError('No EXIF metadata found for ' + self.image_path) geotagging = {} for (idx, tags) in TAGS.items(): if tags == 'GPSInfo': if idx not in self.exif: raise ValueError('No EXIF geotagging found for ' + self.image_path) for (key, val) in GPSTAGS.items(): if key in self.exif[idx]: geotagging[val] = self.exif[idx][key] lat = self.get_decimal_from_dms(geotagging['GPSLatitude'], geotagging['GPSLatitudeRef']) lon = self.get_decimal_from_dms(geotagging['GPSLongitude'], geotagging['GPSLongitudeRef']) return lat, lon
def resize_picture(self, fname, geolocator, angle=0): _TAGS_r = dict(((v, k) for k, v in TAGS.items())) _GPSTAGS_r = dict(((v, k) for k, v in GPSTAGS.items())) th_name = None rz_name = None width = 0 height = 0 try: img = Image.open(fname) width, height = img.size except Exception as e: print('get_picture_data Exception e: ', e, ' fname: ', fname) width = -1 height = -1 return rz_name, th_name, width, height w = int(width) h = int(height) if w > h: w = 800 h = 600 else: w = 600 h = 800 rz_name = self.get_picture_thumbs(w, h, fname, '-resize.JPG', img, angle) w = 128 h = 128 th_name = self.get_picture_thumbs(w, h, fname, '-thumb.JPG', img) return rz_name, th_name, width, height
def _map(self, row, image_binary): try: image = Image.open(StringIO.StringIO(image_binary)) if not hasattr(image, "_getexif"): yield row, json.dumps({}) else: image_tags = image._getexif() if image_tags is None: yield row, json.dumps({}) else: yield row, json.dumps( dict( (name, base64.b64encode(image_tags[id])) if isinstance(image_tags[id], str) else image_tags[id] for id, name in TAGS.items() if id in image_tags ) ) except: sys.stdout.flush() hadoopy.counter("STATUS", "badRows") else: sys.stdout.flush() hadoopy.counter("STATUS", "goodRows")
def get_coordinates(photo): image = Image.open(photo) #print(photo.filename) iphone2.JPG image.verify() if not image._getexif(): return (ValueError("No EXIF metadata found")) # raise ValueError("No EXIF metadata found") exif = image._getexif() #print(exif) geotags = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: return (ValueError("No EXIF geotagging found")) # raise ValueError("No EXIF geotagging found") for (key, val) in GPSTAGS.items(): if key in exif[idx]: geotags[val] = exif[idx][key] coordinates = [] for i in [[geotags['GPSLatitude'], geotags['GPSLatitudeRef']], [geotags['GPSLongitude'], geotags['GPSLongitudeRef']]]: degrees = i[0][0][0] / i[0][0][1] minutes = i[0][1][0] / i[0][1][1] / 60.0 seconds = i[0][2][0] / i[0][2][1] / 3600.0 if i[1] in ['S', 'W']: degrees = -degrees minutes = -minutes seconds = -seconds coordinates.append(round(degrees + minutes + seconds, 3)) return tuple(coordinates)
def rotation_from_exif_tag(img_path): tags_inverted = {v: k for k, v in TAGS.items()} orientation_exif_id = tags_inverted['Orientation'] try: image_exif_tags = Image.open(img_path)._getexif() except: image_exif_tags = None # rotate the image if orientation exif tag is present rotation = 0 if (image_exif_tags is not None) and (orientation_exif_id is not None) and (orientation_exif_id in image_exif_tags): orientation = image_exif_tags[orientation_exif_id] # print ("orientation = " + str(imageExifTags[orientationExifId])) if orientation == 1 or orientation == 0: rotation = 0 # no need to do anything elif orientation == 6: rotation = -90 elif orientation == 8: rotation = 90 else: print("ERROR: orientation = " + str(orientation) + " not_supported!") cv2.error return rotation
def get_geotagging(exif): """Retrieve GPS tags from EXIF Args: exif (object): EXIF object Raises: ValueError: if no EXIF data found ValueError: if no EXIF geotagging data found Returns: dict: Dictionary of EXIF tags """ 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
def registerTag(self, tagName): registered = False for key, value in TAGS.items(): if (tagName == str(value)): self.m_tagFilter.append(key) registered = True if (False == registered): print('Tag not found: ' + tagName)
def get_datetime_orig_exif_tag(exif_data) -> str: """Extracts exif data related to time when photo was taken.""" for (idx, tag) in TAGS.items(): if tag == 'DateTimeOriginal': if idx not in exif_data: raise ValueError("No EXIF DateTimeOriginal found") return exif_data[idx] raise ValueError("No EXIF DateTimeOriginal found")
def print_ExifTagItem(self): """ Affiche dans le terminal tous les noms de TAG Exif :return: na """ if not self.PhotoExif: raise ValueError("No EXIF metadata found") for (idx, tag) in TAGS.items(): print(tag)
def get_geotagging(info): geotagging = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in info: raise ValueError("No EXIF geotagging found") for (key, val) in GPSTAGS.items(): if key in info[idx]: geotagging[val] = info[idx][key] return geotagging
def get_gps_data(image_exif): gps_data = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in image_exif: raise ValueError("No EXIF geotagging found") for (key, val) in GPSTAGS.items(): if key in image_exif[idx]: gps_data[val] = image_exif[idx][key] return gps_data
def get_geotagging(exif): geotagging = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: return None else: for (key, val) in GPSTAGS.items(): if key in exif[idx]: geotagging[val] = exif[idx][key] return geotagging
def get_geo_info(required_exif): if not required_exif: return None geo_info = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in required_exif: return None for (key, val) in GPSTAGS.items(): if key in required_exif[idx]: geo_info[val] = required_exif[idx][key] return geo_info
def _map(self, row, image_binary): image = Image.open(StringIO.StringIO(image_binary)) if not hasattr(image, '_getexif'): yield row, json.dumps({}) else: image_tags = image._getexif() if image_tags is None: yield row, json.dumps({}) else: yield row, json.dumps({name: base64.b64encode(image_tags[id]) if isinstance(image_tags[id], str) else image_tags[id] for id, name in TAGS.items() if id in image_tags})
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
def get_geotagging(exif): """ Returns: Dictionary with following key: value pairs: 'GPSVersionID': bytes, 'GPSLatitudeRef': str = 'N' or 'S', 'GPSLatitude': tuple of tuples, 'GPSLongitudeRef': str = 'E' or 'W', 'GPSLongitude': tuple of tuples, 'GPSAltitudeRef': byte string, 'GPSAltitude': tuple, 'GPSTimeStamp': tuple of tuples, 'GPSSatellites':, 'GPSStatus':, 'GPSMeasureMode':, 'GPSDOP':, 'GPSSpeedRef': str, 'GPSSpeed': tuple, 'GPSImgDirectionRef': str, 'GPSImgDirection': tuple, 'GPSDestBearingRef': str, 'GPSDestBearing': tuple, 'GPSDateStamp': str representing datetime, 'GPSDifferential', 'GPSHPositioningError': tuple, 'GPSTrackRef', 'GPSTrack', 'GPSMapDatum', 'GPSDestLatitudeRef', 'GPSDestLatitude', 'GPSDestLongitudeRef', 'GPSDestLongitude', 'GPSDestDistanceRef', 'GPSDestDistance', 'GPSProcessingMethod', 'GPSAreaInformation', } """ if not exif: raise ValueError("No metadata found please check your camera settings") geotagging = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': geotagging= exif[tag] new = {GPSTAGS[k]: v for k,v in geotagging.items()} return new
def get_geotagging(exif): if not exif: raise ValueError('EXIF not found') geotagging = {} for idx, tag in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: raise ValueError('No EXIF geotagging found') for key, value in GPSTAGS.items(): if key in exif[idx]: geotagging[value] = exif[idx][key] return geotagging
def get_geotagging(self, filename): image = Image.open(filename) exif = image._getexif() geotagging = {} if exif: 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
def get_geotags(lab_exif): # getting the readable geotags if not lab_exif: raise ValueError("No EXIF data found") geotags = {} for (i, tag) in TAGS.items(): if tag == 'GPSInfo': if i not in lab_exif: raise ValueError("No EXIF geotags found") for (j, val) in GPSTAGS.items(): if j in lab_exif[i]: geotags[val] = lab_exif[i][j] return geotags
def func(input_data): image = Image.open(StringIO.StringIO(input_data)) if not hasattr(image, '_getexif'): return json.dumps({}) else: image_tags = image._getexif() if image_tags is None: return json.dumps({}) else: return json.dumps( dict((name, base64.b64encode(image_tags[id]) if isinstance( image_tags[id], str) else image_tags[id]) for id, name in TAGS.items() if id in image_tags))
def get_metadata(image: Image) -> dict: exif_tags = TAGS.items() exif = image._getexif() metadata = {} if not exif: return metadata for k, v in exif_tags: if k in exif: metadata[v] = str(exif[k]) return metadata
def open(self, filename): image = Image.open(str(filename)) image.verify() exif = image._getexif() for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: raise ValueError("No EXIF geotags found") for (key, val) in GPSTAGS.items(): if key in exif[idx]: self.geotags[val] = exif[idx][key]
def get_datetags(exif, filename): if not exif: print("No EXIF metadata found " + filename) if exif: datetagging = {} for (idx, tag) in TAGS.items(): if tag == 'DateTimeOriginal': if idx not in exif: print("No EXIF Date found on " + filename) break for (k, datetagging) in exif.items(): if TAGS.get(k) == 'DateTimeOriginal': return datetagging
def get_GPS(self, img): location = "" geoaxis = {} geotags = {} try: exif = img._getexif() for (idx, tag) in TAGS.items(): if tag != 'GPSInfo': continue if idx not in exif: continue for (key, val) in GPSTAGS.items(): if key in exif[idx]: geotags[val] = exif[idx][key] for axis in ["Latitude", "Longitude"]: dms = geotags[f'GPS{axis}'] ref = geotags[f'GPS{axis}Ref'] degrees = dms[0][0] / dms[0][1] minutes = dms[1][0] / dms[1][1] / 60.0 seconds = dms[2][0] / dms[2][1] / 3600.0 if ref in ['S', 'W']: degrees = -degrees minutes = -minutes seconds = -seconds geoaxis[axis] = round(degrees + minutes + seconds, 5) location = self.geolocator.reverse( "{}, {}".format(geoaxis["Latitude"], geoaxis["Longitude"]) ).raw["address"] # TODO: What can trigger this - make it specific to error. except Exception: return if location: location = sanitize_location(location) if location: return f'{location["town"]}, {location["country"]}' return
def get_metadata(exif): if not exif: raise ValueError("No EXIF metadata found") metadata = {} # info for AM or PM for tag_id in exif: tag = TAGS.get(tag_id, tag_id) data = exif.get(tag_id) if tag == "DateTimeOriginal": time_str = data.split(' ')[1] if int(time_str[0:2]) >= 12: metadata["Time"] = 'PM' else: metadata["Time"] = 'AM' # info for GPS dms = {} geo = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: raise ValueError("No EXIF GeoInfo found") for (key, val) in GPSTAGS.items(): if key in exif[idx]: dms[val] = exif[idx][key] for (key, val) in { 'GPSLatitude': 'GPSLatitudeRef', 'GPSLongitude': 'GPSLongitudeRef' }.items(): degrees = dms[key][0][0] / dms[key][0][1] minutes = dms[key][1][0] / dms[key][1][1] / 60.0 seconds = dms[key][2][0] / dms[key][2][1] / 3600.0 if dms[val] in ['S', 'W']: degrees = -degrees minutes = -minutes seconds = -seconds geo[key] = round(degrees + minutes + seconds, 5) coords = (geo['GPSLatitude'], geo['GPSLongitude']) geocoder = Nominatim(user_agent="aaa") location = geocoder.reverse(coords) metadata['Location'] = location.address.split(', ')[-3] return metadata
def get_exif_geotagging(exif) -> dict: """Gets exif data related to geo coordinates.""" 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
def get_gpstags(exif, filename): if not exif: print("No EXIF metadata found for " + filename) if exif: geotagging = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in exif: print("No EXIF GeoTag found on " + filename) break for (key, val) in GPSTAGS.items(): if key in exif[idx]: geotagging[val] = exif[idx][key] return geotagging
def get_geotagging(self, exif): ''' Extract GPS Info and return ''' logging.debug("Getting GPS Info") 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
def get_start_time(self): exif = _get_exif(self['DEFAULT']['img_directory'] + self['DEFAULT']['img_name_string'].format( self['DEFAULT']['first_img'])) if not exif: raise ValueError("No EXIF metadata found") for (idx, tag) in TAGS.items(): if tag == 'DateTimeOriginal': if idx not in exif: raise ValueError("No EXIF time found") date, time_meta = exif[idx].split(' ') time_img = _get_datetime_from_str(date, time_meta) start_time = time_img - timedelta( seconds=self['DEFAULT'].getint( 'exif_time_infront_real_time')) self['DEFAULT']['start_time'] = start_time.strftime('%H:%M:%S')
def get_geotagging(self): """ Donne les informations du TAG Exif GPS de la photo :return: Ensemble des informations GPS de la photo """ if not self.PhotoExif: #raise ValueError("No EXIF metadata found") return None geotagging = {} for (idx, tag) in TAGS.items(): if tag == 'GPSInfo': if idx not in self.PhotoExif: #raise ValueError("No EXIF geotagging found") return None for (key, val) in GPSTAGS.items(): if key in self.PhotoExif[idx]: geotagging[val] = self.PhotoExif[idx][key] return geotagging
def save_exif(self, img=None, save=True): if img == None: img = Image.open(self.image_file2x.file) exif = img._getexif() tags = {v:k for k, v in TAGS.items()} focal_length_tag = tags['FocalLength'] f_number_tag = tags['FNumber'] iso_speed_tag = tags['ISOSpeedRatings'] exposure_tag = tags['ExposureTime'] gps_info_tag = tags['GPSInfo'] # Finding EXIF focal length self.exif_focal_length = str(exif[focal_length_tag][0]) + 'mm' # Finding EXIF aperture f-number fnumber = float(exif[f_number_tag][0]) / exif[f_number_tag][1] self.exif_aperture = 'ƒ/' + ('%.1f' % fnumber) # Finding EXIF aperture ISO-value self.exif_iso = 'ISO ' + str(exif[iso_speed_tag]) # Finding EXIF aperture shutter duration shutter_divisor = exif[exposure_tag][0] shutter_dividend = exif[exposure_tag][1] if shutter_dividend > 1: self.exif_shutter_speed = str(shutter_divisor) + '/' + str(shutter_dividend) + ' sec' else: self.exif_shutter_speed = str(shutter_divisor) + ' sec' if gps_info_tag in exif: self._set_exif_gps_data(exif[gps_info_tag]) else: print 'Could not save gps exif for image with post id', self.post.id if save: super(Photo, self).save()
def rotationFromExifTag(imgPath): TAGSinverted = {v: k for k, v in TAGS.items()} orientationExifId = TAGSinverted['Orientation'] try: imageExifTags = Image.open(imgPath)._getexif() except: imageExifTags = None # rotate the image if orientation exif tag is present rotation = 0 if imageExifTags != None and orientationExifId != None and orientationExifId in imageExifTags: orientation = imageExifTags[orientationExifId] # print ("orientation = " + str(imageExifTags[orientationExifId])) if orientation == 1 or orientation == 0: rotation = 0 # no need to do anything elif orientation == 6: rotation = -90 elif orientation == 8: rotation = 90 else: print ("ERROR: orientation = " + str(orientation) + " not_supported!") error return rotation
def imread(imgPath): if not os.path.exists(imgPath): "ERROR: image path does not exist." error img = cv2.imread(imgPath) TAGSinverted = {v: k for k, v in TAGS.items()} orientationExifId = TAGSinverted['Orientation'] try: imageExifTags = Image.open(imgPath)._getexif() except: imageExifTags = None #rotate the image if orientation exif tag is present if imageExifTags != None and orientationExifId != None and orientationExifId in imageExifTags: orientation = imageExifTags[orientationExifId] #print "orientation = " + str(imageExifTags[orientationExifId]) if orientation == 1 or orientation == 0: pass #no need to do anything elif orientation == 8: img = imrotate(img, 90) else: print "ERROR: orientation = " + str(orientation) + " not_supported!" error return img
from PIL import Image, ImageOps from PIL.ExifTags import TAGS, GPSTAGS import exifread import logging log = logging.getLogger(__name__) tag_name_to_id = dict([ (v, k) for k, v in TAGS.items() ]) tag_name_to_id[2] = 'GPSLatitude' tag_name_to_id[4] = 'GPSLongitude' tag_name_to_id[8] = 'GPSSatellites' tag_name_to_id[9] = 'GPSStatus' tag_name_to_id[256] = 'ImageWidth' tag_name_to_id[257] = 'ImageLength' tag_name_to_id[258] = 'BitsPerSample' tag_name_to_id[270] = 'ImageDescription' tag_name_to_id[271] = 'Make' tag_name_to_id[272] = 'Model' tag_name_to_id[274] = 'Orientation' tag_name_to_id[282] = 'XResolution' tag_name_to_id[283] = 'YResolution' tag_name_to_id[305] = 'Software' tag_name_to_id[306] = 'DateTime' tag_name_to_id[315] = 'Artist' tag_name_to_id[316] = 'HostComputer' tag_name_to_id[37378] = 'ApertureValue' tag_name_to_id[33432] = 'Copyright' tag_name_to_id[33434] = 'ExposureTime' tag_name_to_id[33437] = 'FNumber' tag_name_to_id[34855] = 'ISOSpeedRatings' tag_name_to_id[37381] = 'MaxApertureValue' tag_name_to_id[37386] = 'FocalLength'
from PIL import Image from PIL.ExifTags import TAGS ORIENTATION_TAG_ID = [k for k, v in TAGS.items() if v == 'Orientation'][0] ROTATION_ANGLES = { 1: 0, # 'Horizontal (normal)' 2: 180, # 'Mirrored horizontal', 3: 180, # 'Rotated 180', 4: 0, # 'Mirrored vertical', 5: -90, # 'Mirrored horizontal then rotated 90 CCW', 6: -90, # 'Rotated 90 CW', 7: 90, # 'Mirrored horizontal then rotated 90 CW', 8: 90, # 'Rotated 90 CCW' } def resize(in_filename, out_filename, width=1024, rotate=True): if in_filename != out_filename: im = Image.open(in_filename) exifdict = im._getexif() if rotate and exifdict and exifdict.get(ORIENTATION_TAG_ID): rotate_angle = ROTATION_ANGLES.get(exifdict[ORIENTATION_TAG_ID], 0) im = im.rotate(rotate_angle) scale = float(width) / float(im.size[0]) im = im.resize([int(scale * s) for s in im.size], Image.ANTIALIAS) im.save(out_filename, "JPEG", quality=75) else:
from PIL import Image from PIL.ExifTags import TAGS for tag, name in TAGS.items(): if name == "Orientation": ORIENTATION = tag break def orientate(image, value): if value in (2, 5): image = image.transpose(Image.FLIP_LEFT_RIGHT) if value in (4, 7): image = image.transpose(Image.FLIP_TOP_BOTTOM) if value in (5, 7, 8): image = image.transpose(Image.ROTATE_90) if value == 3: image = image.transpose(Image.ROTATE_180) if value == 6: image = image.transpose(Image.ROTATE_270) return image def create_thumbnail(image, size): thumbnail = Image.new("RGB", image.size, (255,255,255)) if len(image.split()) > 3: thumbnail.paste(image, mask=image.split()[3]) else: thumbnail.paste(image) if hasattr(image, "_getexif") and image._getexif(): thumbnail = orientate(thumbnail, image._getexif().get(ORIENTATION, 1))
# coding: utf-8 from PIL.ExifTags import TAGS, GPSTAGS RTAGS = {v: k for (k, v) in TAGS.items()} RGPSTAGS = {v: k for (k, v) in GPSTAGS.items()} GPSINFO = RTAGS["GPSInfo"] def coord_to_deg(values): # every coordinate is a list of 3 pairs # every pair is a fraction ( (n, d) -> n/d ) # the 3 values are °, ' and " (degree, minute and second) deg = 0 for i in range(3): (n, d) = values[i] if d != 0: deg += n/(d * (60.**i)) return deg def extract_location(image): if not hasattr(image, "_getexif"): return {} exif = image._getexif() if not exif: return {} try: gpsinfo = exif[GPSINFO] lat = coord_to_deg(gpsinfo[RGPSTAGS["GPSLatitude"]]) if gpsinfo[RGPSTAGS["GPSLatitudeRef"]] == "S": lat = -lat lng = coord_to_deg(gpsinfo[RGPSTAGS["GPSLongitude"]])