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

This comment has been minimized.

Copy link

jannecederberg commented Aug 17, 2016

Great gist!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.