Skip to content

Commit de539ac

Browse files
author
api.jscudder
committed
Added media, geo, and exif modules for use in the photos package.
1 parent 0d4c115 commit de539ac

3 files changed

Lines changed: 669 additions & 0 deletions

File tree

src/gdata/exif/__init__.py

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# -*-*- encoding: utf-8 -*-*-
2+
#
3+
# This is gdata.photos.exif, implementing the exif namespace in gdata
4+
#
5+
# $Id: __init__.py 81 2007-10-03 14:41:42Z havard.gulldahl $
6+
#
7+
# Copyright 2007 Håvard Gulldahl
8+
# Portions copyright 2007 Google Inc.
9+
#
10+
# Licensed under the Apache License, Version 2.0 (the "License");
11+
# you may not use this file except in compliance with the License.
12+
# You may obtain a copy of the License at
13+
#
14+
# http://www.apache.org/licenses/LICENSE-2.0
15+
#
16+
# Unless required by applicable law or agreed to in writing, software
17+
# distributed under the License is distributed on an "AS IS" BASIS,
18+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+
# See the License for the specific language governing permissions and
20+
# limitations under the License.
21+
22+
"""This module maps elements from the {EXIF} namespace[1] to GData objects.
23+
These elements describe image data, using exif attributes[2].
24+
25+
Picasa Web Albums uses the exif namespace to represent Exif data encoded
26+
in a photo [3].
27+
28+
Picasa Web Albums uses the following exif elements:
29+
exif:distance
30+
exif:exposure
31+
exif:flash
32+
exif:focallength
33+
exif:fstop
34+
exif:imageUniqueID
35+
exif:iso
36+
exif:make
37+
exif:model
38+
exif:tags
39+
exif:time
40+
41+
[1]: http://schemas.google.com/photos/exif/2007.
42+
[2]: http://en.wikipedia.org/wiki/Exif
43+
[3]: http://code.google.com/apis/picasaweb/reference.html#exif_reference
44+
"""
45+
46+
47+
__author__ = u'havard@gulldahl.no'# (Håvard Gulldahl)' #BUG: pydoc chokes on non-ascii chars in __author__
48+
__license__ = 'Apache License v2'
49+
50+
try:
51+
from xml.etree import cElementTree as ElementTree
52+
except ImportError:
53+
try:
54+
import cElementTree as ElementTree
55+
except ImportError:
56+
from elementtree import ElementTree
57+
import atom
58+
import gdata
59+
60+
EXIF_NAMESPACE = 'http://schemas.google.com/photos/exif/2007'
61+
62+
class ExifBaseElement(atom.AtomBase):
63+
"""Base class for elements in the EXIF_NAMESPACE (%s). To add new elements, you only need to add the element tag name to self._tag
64+
""" % EXIF_NAMESPACE
65+
66+
_tag = ''
67+
_namespace = EXIF_NAMESPACE
68+
_children = atom.AtomBase._children.copy()
69+
_attributes = atom.AtomBase._attributes.copy()
70+
71+
def __init__(self, name=None, extension_elements=None,
72+
extension_attributes=None, text=None):
73+
self.name = name
74+
self.text = text
75+
self.extension_elements = extension_elements or []
76+
self.extension_attributes = extension_attributes or {}
77+
78+
class Distance(ExifBaseElement):
79+
"(float) The distance to the subject, e.g. 0.0"
80+
81+
_tag = 'distance'
82+
def DistanceFromString(xml_string):
83+
return atom.CreateClassFromXMLString(Distance, xml_string)
84+
85+
class Exposure(ExifBaseElement):
86+
"(float) The exposure time used, e.g. 0.025 or 8.0E4"
87+
88+
_tag = 'exposure'
89+
def ExposureFromString(xml_string):
90+
return atom.CreateClassFromXMLString(Exposure, xml_string)
91+
92+
class Flash(ExifBaseElement):
93+
"""(string) Boolean value indicating whether the flash was used.
94+
The .text attribute will either be `true' or `false'
95+
96+
As a convenience, this object's .bool method will return what you want,
97+
so you can say:
98+
99+
flash_used = bool(Flash)
100+
101+
"""
102+
103+
_tag = 'flash'
104+
def __bool__(self):
105+
if self.text.lower() in ('true','false'):
106+
return self.text.lower() == 'true'
107+
def FlashFromString(xml_string):
108+
return atom.CreateClassFromXMLString(Flash, xml_string)
109+
110+
class Focallength(ExifBaseElement):
111+
"(float) The focal length used, e.g. 23.7"
112+
113+
_tag = 'focallength'
114+
def FocallengthFromString(xml_string):
115+
return atom.CreateClassFromXMLString(Focallength, xml_string)
116+
117+
class Fstop(ExifBaseElement):
118+
"(float) The fstop value used, e.g. 5.0"
119+
120+
_tag = 'fstop'
121+
def FstopFromString(xml_string):
122+
return atom.CreateClassFromXMLString(Fstop, xml_string)
123+
124+
class ImageUniqueID(ExifBaseElement):
125+
"(string) The unique image ID for the photo. Generated by Google Photo servers"
126+
127+
_tag = 'imageUniqueID'
128+
def ImageUniqueIDFromString(xml_string):
129+
return atom.CreateClassFromXMLString(ImageUniqueID, xml_string)
130+
131+
class Iso(ExifBaseElement):
132+
"(int) The iso equivalent value used, e.g. 200"
133+
134+
_tag = 'iso'
135+
def IsoFromString(xml_string):
136+
return atom.CreateClassFromXMLString(Iso, xml_string)
137+
138+
class Make(ExifBaseElement):
139+
"(string) The make of the camera used, e.g. Fictitious Camera Company"
140+
141+
_tag = 'make'
142+
def MakeFromString(xml_string):
143+
return atom.CreateClassFromXMLString(Make, xml_string)
144+
145+
class Model(ExifBaseElement):
146+
"(string) The model of the camera used,e.g AMAZING-100D"
147+
148+
_tag = 'model'
149+
def ModelFromString(xml_string):
150+
return atom.CreateClassFromXMLString(Model, xml_string)
151+
152+
class Time(ExifBaseElement):
153+
"""(int) The date/time the photo was taken, e.g. 1180294337000.
154+
Represented as the number of milliseconds since January 1st, 1970.
155+
156+
The value of this element will always be identical to the value
157+
of the <gphoto:timestamp>.
158+
159+
Look at this object's .isoformat() for a human friendly datetime string:
160+
161+
photo_epoch = Time.text # 1180294337000
162+
photo_isostring = Time.isoformat() # '2007-05-27T19:32:17.000Z'
163+
164+
Alternatively:
165+
photo_datetime = Time.datetime() # (requires python >= 2.3)
166+
"""
167+
168+
_tag = 'time'
169+
def isoformat(self):
170+
"""(string) Return the timestamp as a ISO 8601 formatted string,
171+
e.g. '2007-05-27T19:32:17.000Z'
172+
"""
173+
import time
174+
epoch = float(self.text)/1000
175+
return time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime(epoch))
176+
177+
def datetime(self):
178+
"""(datetime.datetime) Return the timestamp as a datetime.datetime object
179+
180+
Requires python 2.3
181+
"""
182+
import datetime
183+
epoch = float(self.text)/1000
184+
return datetime.datetime.fromtimestamp(epoch)
185+
186+
def TimeFromString(xml_string):
187+
return atom.CreateClassFromXMLString(Time, xml_string)
188+
189+
class Tags(ExifBaseElement):
190+
"""The container for all exif elements.
191+
The <exif:tags> element can appear as a child of a photo entry.
192+
"""
193+
194+
_tag = 'tags'
195+
_children = atom.AtomBase._children.copy()
196+
_children['{%s}fstop' % EXIF_NAMESPACE] = ('fstop', Fstop)
197+
_children['{%s}make' % EXIF_NAMESPACE] = ('make', Make)
198+
_children['{%s}model' % EXIF_NAMESPACE] = ('model', Model)
199+
_children['{%s}distance' % EXIF_NAMESPACE] = ('distance', Distance)
200+
_children['{%s}exposure' % EXIF_NAMESPACE] = ('exposure', Exposure)
201+
_children['{%s}flash' % EXIF_NAMESPACE] = ('flash', Flash)
202+
_children['{%s}focallength' % EXIF_NAMESPACE] = ('focallength', Focallength)
203+
_children['{%s}iso' % EXIF_NAMESPACE] = ('iso', Iso)
204+
_children['{%s}time' % EXIF_NAMESPACE] = ('time', Time)
205+
_children['{%s}imageUniqueID' % EXIF_NAMESPACE] = ('imageUniqueID', ImageUniqueID)
206+
207+
def __init__(self, extension_elements=None, extension_attributes=None, text=None):
208+
ExifBaseElement.__init__(self, extension_elements=extension_elements,
209+
extension_attributes=extension_attributes,
210+
text=text)
211+
self.fstop=None
212+
self.make=None
213+
self.model=None
214+
self.distance=None
215+
self.exposure=None
216+
self.flash=None
217+
self.focallength=None
218+
self.iso=None
219+
self.time=None
220+
self.imageUniqueID=None
221+
def TagsFromString(xml_string):
222+
return atom.CreateClassFromXMLString(Tags, xml_string)
223+

0 commit comments

Comments
 (0)