Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Dump metadata from panorama photos shot by Photosphere App
#!/usr/bin/env python
Dump metadata from panorama photos shot by Photosphere App
@author: @CodeColorist
Photo Sphere XMP Metadata document
import xml.etree.ElementTree as ET
import json
import sys
from PIL import Image, ExifTags
def parse(val):
"""parse literal to actual value"""
literal = {
'True': True,
'False': False
if val in literal:
return literal.get(val)
elif val.isdigit():
return int(val)
return float(val)
except ValueError:
return val
def dump_meta(filename, format='json'):
ns = {
'GPano': '',
'rdf': ''
with as im:
metainfo = {
ExifTags.TAGS[k]: v
for k, v in im._getexif().items()
if k in ExifTags.TAGS
pano_prefix = '{%s}' % ns['GPano']
for segment, content in im.applist:
marker, body = content.split('\x00', 1)
if segment == 'APP1' and marker == '':
root = ET.fromstring(body)
node = root.find('rdf:RDF', ns).find('rdf:Description', ns)
metainfo.update({key[len(pano_prefix):]: parse(node.get(key))
for key in node.keys() if key.startswith(pano_prefix)})
if format == 'json':
return json.dumps(metainfo, sort_keys=True, separators=(',', ': '), indent=2)
elif format == 'text':
return '\n'.join(['{0:32} {1}'.format(item, metainfo[item]) for item in metainfo])
raise ValueError('Invalid format: %s' % format)
if __name__ == '__main__':
argc = len(sys.argv)
if argc in (2, 3):
print_in_json = 'json' if sys.argv[1] == '--json' else 'text'
report = dump_meta(sys.argv[argc - 1], format=print_in_json)
sys.stderr.write('Usage: %s [--json] FILENAME\n' % sys.argv[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment