Skip to content

Instantly share code, notes, and snippets.

Embed
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
Usage
@author: @CodeColorist
@site: http://chichou.0ginr.com/blog
Photo Sphere XMP Metadata document
https://developers.google.com/photo-sphere/metadata/
"""
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)
else:
try:
return float(val)
except ValueError:
return val
def dump_meta(filename, format='json'):
ns = {
'GPano': 'http://ns.google.com/photos/1.0/panorama/',
'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
}
with Image.open(filename) 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)
# XMP
if segment == 'APP1' and marker == 'http://ns.adobe.com/xap/1.0/':
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])
else:
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.stdout.write(report)
else:
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