annotate data/plugin/macro/Image.py @ 308:81a4a9a1f497

macro.Image: div container for output of exif time added
author Reimar Bauer <rb.proj AT googlemail DOT com>
date Thu, 27 Nov 2008 10:42:07 +0100
parents 3126b6ff38fa
children da0bb5e04a91
rev   line source
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
1 # -*- coding: iso-8859-1 -*-
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
2 """
267
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
3 MoinMoin - Image rendering support class and a simple macro using it.
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
4
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
5 Features:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
6 * rendering (and caching) of thumbnails/webnails/originals
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
7 * gives ready-to-use image urls
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
8 * auto-rotation based on EXIF information
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
9 * determines creation time from EXIF or file system
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
10 * easy access to some EXIF data (cached)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
11
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
12 Requires PIL and ExifTags libs.
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
13
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
14 @copyright: 2008 MoinMoin:ThomasWaldmann,
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
15 2008 MoinMoin:ReimarBauer
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
16 @license: GNU GPL, see COPYING for details.
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
17 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
18
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
19 import os, time
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
20 import StringIO
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
21
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
22 from MoinMoin import caching, wikiutil
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
23 from MoinMoin.action import AttachFile, cache
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
24
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
25 try:
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
26 from PIL import Image as PILImage
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
27 except ImportError:
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
28 PILImage = None
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
29 try:
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
30 from PIL import IptcImagePlugin as PILIptc
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
31 except ImportError:
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
32 PILIptc = None
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
33
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
34 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
35 import ExifTags
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
36 except ImportError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
37 ExifTags = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
38
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
39 class Image(object):
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
40 # predefined sizes (width, height) - use them if you like:
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
41 WEBNAIL_SIZE = (640, 480)
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
42 THUMBNAIL_SIZE = (128, 128)
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
43
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
44 # we don't process and cache all EXIF infos, but just these:
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
45 EXIF_CACHED = set(['DateTimeOriginal', 'TimeZoneOffset', 'Orientation', ])
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
46
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
47 def __init__(self, request,
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
48 item_name, # PageName/AttachName for now, later this is just the item name
267
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
49 headline=None,
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
50 caption=None,
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
51 ):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
52 self.request = request
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
53 self.pagename, self.attachname = item_name.rsplit('/', 1)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
54
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
55 # cached property values:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
56 self.__filename = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
57 self.__content_type = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
58 self.__cache_key = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
59 self.__image = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
60 self.__exif = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
61 self.__ctime = None
267
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
62 self.__headline = headline
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
63 self.__caption = caption
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
64
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
65 def _get_filename(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
66 if self.__filename is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
67 self.__filename = AttachFile.getFilename(self.request, self.pagename, self.attachname)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
68 return self.__filename
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
69 _filename = property(_get_filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
70
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
71 def _get_content_type(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
72 if self.__content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
73 self.__content_type = wikiutil.MimeType(filename=self._filename).mime_type()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
74 return self.__content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
75 content_type = property(_get_content_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
76
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
77 def _get_image(self):
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
78 if self.__image is None and PILImage is not None:
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
79 self.__image = PILImage.open(self._filename)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
80 return self.__image
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
81 image = property(_get_image) # the original image (PIL Image object) or None
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
82
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
83 def _get_cache_key(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
84 if self.__cache_key is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
85 self.__cache_key = cache.key(self.request, itemname=self.pagename, attachname=self.attachname)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
86 return self.__cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
87 _cache_key = property(_get_cache_key)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
88
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
89 def _get_exif_data(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
90 """ return exif data for this image, use a cache for them """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
91 if self.__exif is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
92 key = self._cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
93 exif_cache = caching.CacheEntry(self.request, 'exif', key, 'wiki',
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
94 use_pickle=True, do_locking=False)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
95 if not exif_cache.exists():
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
96 # we don't want to cache all EXIF data, just a few interesting values
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
97 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
98 exif_data = {}
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
99 if self.image is not None: # we have PIL
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
100 for tag, value in self.image._getexif().items():
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
101 tag_name = ExifTags.TAGS.get(tag)
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
102 if tag_name in self.EXIF_CACHED:
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
103 exif_data[tag_name] = value
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
104 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
105 time_str = exif_data['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
106 tm = time.strptime(time_str, "%Y:%m:%d %H:%M:%S")
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
107 t = time.mktime(tm)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
108 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
109 tz_str = exif_data['TimeZoneOffset']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
110 tz_offset = int(tz_str) * 3600
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
111 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
112 tz_offset = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
113 # mktime is inverse function of (our) localtime, adjust by time.timezone
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
114 t -= time.timezone + tz_offset
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
115 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
116 t = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
117 exif_data['DateTimeOriginal'] = t
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
118 except (IOError, AttributeError):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
119 exif_data = {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
120 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
121 iptc_data = {}
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
122 if self.image is not None and PILIptc: # we have PIL and the IPTC plugin
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
123 iptc = PILIptc.getiptcinfo(self.image) or {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
124 for name, key in [
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
125 ('headline', (2, 105)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
126 ('caption', (2, 120)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
127 ('copyright', (2, 116)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
128 ('keywords', (2, 25)), ]:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
129 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
130 iptc_data[name] = iptc[key]
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
131 except KeyError:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
132 pass
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
133 except:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
134 iptc_data = {}
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
135 cache_data = (exif_data, iptc_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
136 exif_cache.update(cache_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
137 self.__exif, self.__iptc = cache_data
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
138 else:
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
139 self.__exif, self.__iptc = exif_cache.content()
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
140 return self.__exif, self.__iptc
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
141 exif = property(lambda self: self._get_exif_data()[0]) # dict of preprocessed EXIF data (string -> value)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
142 iptc = property(lambda self: self._get_exif_data()[1]) # dict of preprocessed IPTC data (string -> value)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
143
267
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
144 def _get_headline(self):
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
145 if self.__headline is None:
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
146 self.__headline = self.iptc.get('headline', u'')
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
147 return self.__headline
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
148 headline = property(_get_headline)
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
149
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
150 def _get_caption(self):
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
151 if self.__caption is None:
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
152 self.__caption = self.iptc.get('caption', u'')
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
153 return self.__caption
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
154 caption = property(_get_caption)
de2f265a9ac5 Image: add headline/caption support, read from iptc data if not given
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 266
diff changeset
155
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
156 def _get_ctime(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
157 """ return creation time of image (either from EXIF or file date) as UNIX timestamp """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
158 if self.__ctime is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
159 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
160 ctime = self.exif['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
161 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
162 ctime = os.path.getctime(self._filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
163 self.__ctime = ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
164 return self.__ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
165 ctime = property(_get_ctime)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
166
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
167 def _transform(self, size=None, content_type=None, transpose_op=None):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
168 """ resize to new size (optional), transpose according to exif infos,
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
169 return data as content_type (default: same ct as original image)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
170 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
171 if content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
172 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
173 if content_type == 'image/jpeg':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
174 output_type = 'JPEG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
175 elif content_type == 'image/png':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
176 output_type = 'PNG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
177 elif content_type == 'image/gif':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
178 output_type = 'GIF'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
179 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
180 raise ValueError("content_type %r not supported" % content_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
181 image = self.image
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
182 if image is not None: # we have PIL
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
183 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
184 # if we have EXIF data, we can transpose (e.g. rotate left),
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
185 # so the rendered image is correctly oriented:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
186 transpose_op = transpose_op or self.exif['Orientation']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
187 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
188 transpose_op = 1 # no change
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
189
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
190 if size is not None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
191 image = image.copy() # create copy first as thumbnail works in-place
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
192 image.thumbnail(size, PILImage.ANTIALIAS)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
193
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
194 transpose_func = {
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
195 1: lambda image: image,
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
196 2: lambda image: image.transpose(PILImage.FLIP_LEFT_RIGHT),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
197 3: lambda image: image.transpose(PILImage.ROTATE_180),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
198 4: lambda image: image.transpose(PILImage.FLIP_TOP_BOTTOM),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
199 5: lambda image: image.transpose(PILImage.ROTATE_90).transpose(PILImage.FLIP_TOP_BOTTOM),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
200 6: lambda image: image.transpose(PILImage.ROTATE_270),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
201 7: lambda image: image.transpose(PILImage.ROTATE_90).transpose(PILImage.FLIP_LEFT_RIGHT),
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
202 8: lambda image: image.transpose(PILImage.ROTATE_90),
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
203 }
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
204 image = transpose_func[transpose_op](image)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
205
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
206 buf = StringIO.StringIO()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
207 image.save(buf, output_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
208 buf.flush() # XXX needed?
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
209 data = buf.getvalue()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
210 buf.close()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
211 else: # XXX what to do without PIL?
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
212 data = ''
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
213 return content_type, data
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
214
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
215 def url(self, size=None):
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
216 """ return a cache url for a rendering of this image with specified size -
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
217 the code automatically makes sure that the cache contains that rendering.
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
218 If size is None, it gives a url for the full image size rendering.
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
219 Otherwise, size has to be a tuple (w, h) - if you like, you can use
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
220 these class level constant sizes:
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
221 WEBNAIL_SIZE - medium size, one of those likely to fit in a browser window
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
222 THUMBNAIL_SIZE - small size, for showing collections
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
223 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
224 request = self.request
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
225 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
226 if size is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
227 size_str = 'orig'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
228 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
229 size_str = '%d_%d' % size
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
230 key = '%s_%s_%s' % (content_type.replace('/', '_'), size_str, self._cache_key)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
231 if not cache.exists(request, key):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
232 content_type, data = self._transform(size=size, content_type=content_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
233 cache.put(request, key, data, content_type=content_type)
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
234 return cache.url(request, key)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
235
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
236
305
e94b38f4ba6b macro.Image: description added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 302
diff changeset
237 def macro_Image(macro, itemname=wikiutil.required_arg(unicode), width=9999, height=9999, alt=u'', description=u''):
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
238 """ Embed an Image into a wiki page.
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
239
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
240 We use a very high default value for width and height, because PIL will calculate the
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
241 image dimensions to not be larger than (width, height) and also not be larger than
266
3e4eaae2f7df add support for just giving the attachment name, fix typo
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 265
diff changeset
242 the original image. Thus, by not giving width or height, you'll get the original image,
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
243 and if you specify width or height you will get an image of that width or that height.
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
244
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
245 <<Image(PageName/attachname,width=100,alt="sample image")>>
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
246 """
266
3e4eaae2f7df add support for just giving the attachment name, fix typo
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 265
diff changeset
247 if '/' not in itemname:
3e4eaae2f7df add support for just giving the attachment name, fix typo
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 265
diff changeset
248 itemname = macro.formatter.page.page_name + '/' + itemname
299
1c25a98e3d9d reverted changeset 269:1e3e876e38fb for Image and partly for text_x_arnica
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 278
diff changeset
249 img = Image(macro.request, itemname, caption=alt)
308
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
250 return "%s%s%s%s%s%s%s%s%s%s%s" % ('<div class="thumbnail">',
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
251 macro.formatter.image(src=img.url((width, height)), alt=img.caption),
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
252 '<div class="decription">',
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
253 '<div style="width:%spx">' % (width),
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
254 macro.formatter.text(description),
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
255 '<div class="html-show-date">',
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
256 macro.request.user.getFormattedDateTime(img.ctime),
81a4a9a1f497 macro.Image: div container for output of exif time added
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 307
diff changeset
257 '</div>', '</div>', '</div>', '</div>')
299
1c25a98e3d9d reverted changeset 269:1e3e876e38fb for Image and partly for text_x_arnica
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 278
diff changeset
258