/gdata/exif/__init__.py
Python | 217 lines | 166 code | 7 blank | 44 comment | 2 complexity | b1f9439f014126422f0ff32b34fa592d MD5 | raw file
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. 23These elements describe image data, using exif attributes[2]. 24 25Picasa Web Albums uses the exif namespace to represent Exif data encoded 26in a photo [3]. 27 28Picasa Web Albums uses the following exif elements: 29exif:distance 30exif:exposure 31exif:flash 32exif:focallength 33exif:fstop 34exif:imageUniqueID 35exif:iso 36exif:make 37exif:model 38exif:tags 39exif: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 51import atom 52import gdata 53 54EXIF_NAMESPACE = 'http://schemas.google.com/photos/exif/2007' 55 56class ExifBaseElement(atom.AtomBase): 57 """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 58 """ % EXIF_NAMESPACE 59 60 _tag = '' 61 _namespace = EXIF_NAMESPACE 62 _children = atom.AtomBase._children.copy() 63 _attributes = atom.AtomBase._attributes.copy() 64 65 def __init__(self, name=None, extension_elements=None, 66 extension_attributes=None, text=None): 67 self.name = name 68 self.text = text 69 self.extension_elements = extension_elements or [] 70 self.extension_attributes = extension_attributes or {} 71 72class Distance(ExifBaseElement): 73 "(float) The distance to the subject, e.g. 0.0" 74 75 _tag = 'distance' 76def DistanceFromString(xml_string): 77 return atom.CreateClassFromXMLString(Distance, xml_string) 78 79class Exposure(ExifBaseElement): 80 "(float) The exposure time used, e.g. 0.025 or 8.0E4" 81 82 _tag = 'exposure' 83def ExposureFromString(xml_string): 84 return atom.CreateClassFromXMLString(Exposure, xml_string) 85 86class Flash(ExifBaseElement): 87 """(string) Boolean value indicating whether the flash was used. 88 The .text attribute will either be `true' or `false' 89 90 As a convenience, this object's .bool method will return what you want, 91 so you can say: 92 93 flash_used = bool(Flash) 94 95 """ 96 97 _tag = 'flash' 98 def __bool__(self): 99 if self.text.lower() in ('true','false'): 100 return self.text.lower() == 'true' 101def FlashFromString(xml_string): 102 return atom.CreateClassFromXMLString(Flash, xml_string) 103 104class Focallength(ExifBaseElement): 105 "(float) The focal length used, e.g. 23.7" 106 107 _tag = 'focallength' 108def FocallengthFromString(xml_string): 109 return atom.CreateClassFromXMLString(Focallength, xml_string) 110 111class Fstop(ExifBaseElement): 112 "(float) The fstop value used, e.g. 5.0" 113 114 _tag = 'fstop' 115def FstopFromString(xml_string): 116 return atom.CreateClassFromXMLString(Fstop, xml_string) 117 118class ImageUniqueID(ExifBaseElement): 119 "(string) The unique image ID for the photo. Generated by Google Photo servers" 120 121 _tag = 'imageUniqueID' 122def ImageUniqueIDFromString(xml_string): 123 return atom.CreateClassFromXMLString(ImageUniqueID, xml_string) 124 125class Iso(ExifBaseElement): 126 "(int) The iso equivalent value used, e.g. 200" 127 128 _tag = 'iso' 129def IsoFromString(xml_string): 130 return atom.CreateClassFromXMLString(Iso, xml_string) 131 132class Make(ExifBaseElement): 133 "(string) The make of the camera used, e.g. Fictitious Camera Company" 134 135 _tag = 'make' 136def MakeFromString(xml_string): 137 return atom.CreateClassFromXMLString(Make, xml_string) 138 139class Model(ExifBaseElement): 140 "(string) The model of the camera used,e.g AMAZING-100D" 141 142 _tag = 'model' 143def ModelFromString(xml_string): 144 return atom.CreateClassFromXMLString(Model, xml_string) 145 146class Time(ExifBaseElement): 147 """(int) The date/time the photo was taken, e.g. 1180294337000. 148 Represented as the number of milliseconds since January 1st, 1970. 149 150 The value of this element will always be identical to the value 151 of the <gphoto:timestamp>. 152 153 Look at this object's .isoformat() for a human friendly datetime string: 154 155 photo_epoch = Time.text # 1180294337000 156 photo_isostring = Time.isoformat() # '2007-05-27T19:32:17.000Z' 157 158 Alternatively: 159 photo_datetime = Time.datetime() # (requires python >= 2.3) 160 """ 161 162 _tag = 'time' 163 def isoformat(self): 164 """(string) Return the timestamp as a ISO 8601 formatted string, 165 e.g. '2007-05-27T19:32:17.000Z' 166 """ 167 import time 168 epoch = float(self.text)/1000 169 return time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime(epoch)) 170 171 def datetime(self): 172 """(datetime.datetime) Return the timestamp as a datetime.datetime object 173 174 Requires python 2.3 175 """ 176 import datetime 177 epoch = float(self.text)/1000 178 return datetime.datetime.fromtimestamp(epoch) 179 180def TimeFromString(xml_string): 181 return atom.CreateClassFromXMLString(Time, xml_string) 182 183class Tags(ExifBaseElement): 184 """The container for all exif elements. 185 The <exif:tags> element can appear as a child of a photo entry. 186 """ 187 188 _tag = 'tags' 189 _children = atom.AtomBase._children.copy() 190 _children['{%s}fstop' % EXIF_NAMESPACE] = ('fstop', Fstop) 191 _children['{%s}make' % EXIF_NAMESPACE] = ('make', Make) 192 _children['{%s}model' % EXIF_NAMESPACE] = ('model', Model) 193 _children['{%s}distance' % EXIF_NAMESPACE] = ('distance', Distance) 194 _children['{%s}exposure' % EXIF_NAMESPACE] = ('exposure', Exposure) 195 _children['{%s}flash' % EXIF_NAMESPACE] = ('flash', Flash) 196 _children['{%s}focallength' % EXIF_NAMESPACE] = ('focallength', Focallength) 197 _children['{%s}iso' % EXIF_NAMESPACE] = ('iso', Iso) 198 _children['{%s}time' % EXIF_NAMESPACE] = ('time', Time) 199 _children['{%s}imageUniqueID' % EXIF_NAMESPACE] = ('imageUniqueID', ImageUniqueID) 200 201 def __init__(self, extension_elements=None, extension_attributes=None, text=None): 202 ExifBaseElement.__init__(self, extension_elements=extension_elements, 203 extension_attributes=extension_attributes, 204 text=text) 205 self.fstop=None 206 self.make=None 207 self.model=None 208 self.distance=None 209 self.exposure=None 210 self.flash=None 211 self.focallength=None 212 self.iso=None 213 self.time=None 214 self.imageUniqueID=None 215def TagsFromString(xml_string): 216 return atom.CreateClassFromXMLString(Tags, xml_string) 217