annotate data/plugin/macro/Image.py @ 266:3e4eaae2f7df

add support for just giving the attachment name, fix typo
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 14 Sep 2008 00:15:21 +0200
parents 37b96db69d0e
children de2f265a9ac5
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 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
3 MoinMoin - MoinImage image rendering support class and a test macro using it.
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
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
49 description=u'', # we just store this, but we do not use it in Image
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
50 ):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
51 self.request = request
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
52 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
53 self.description = description
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
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
62
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
63 def _get_filename(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
64 if self.__filename is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
65 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
66 return self.__filename
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
67 _filename = property(_get_filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
68
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
69 def _get_content_type(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
70 if self.__content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
71 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
72 return self.__content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
73 content_type = property(_get_content_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
74
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
75 def _get_image(self):
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
76 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
77 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
78 return self.__image
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
79 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
80
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
81 def _get_cache_key(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
82 if self.__cache_key is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
83 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
84 return self.__cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
85 _cache_key = property(_get_cache_key)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
86
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
87 def _get_exif_data(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
88 """ 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
89 if self.__exif is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
90 key = self._cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
91 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
92 use_pickle=True, do_locking=False)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
93 if not exif_cache.exists():
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
94 # 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
95 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
96 exif_data = {}
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
97 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
98 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
99 tag_name = ExifTags.TAGS.get(tag)
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
100 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
101 exif_data[tag_name] = value
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
102 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
103 time_str = exif_data['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
104 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
105 t = time.mktime(tm)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
106 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
107 tz_str = exif_data['TimeZoneOffset']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
108 tz_offset = int(tz_str) * 3600
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
109 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
110 tz_offset = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
111 # 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
112 t -= time.timezone + tz_offset
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
113 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
114 t = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
115 exif_data['DateTimeOriginal'] = t
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
116 except (IOError, AttributeError):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
117 exif_data = {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
118 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
119 iptc_data = {}
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
120 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
121 iptc = PILIptc.getiptcinfo(self.image) or {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
122 for name, key in [
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
123 ('headline', (2, 105)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
124 ('caption', (2, 120)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
125 ('copyright', (2, 116)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
126 ('keywords', (2, 25)), ]:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
127 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
128 iptc_data[name] = iptc[key]
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
129 except KeyError:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
130 pass
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
131 except:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
132 iptc_data = {}
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
133 cache_data = (exif_data, iptc_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
134 exif_cache.update(cache_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
135 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
136 else:
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
137 self.__exif, self.__iptc = exif_cache.content()
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
138 return self.__exif, self.__iptc
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
139 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
140 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
141
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
142 def _get_ctime(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
143 """ 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
144 if self.__ctime is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
145 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
146 ctime = self.exif['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
147 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
148 ctime = os.path.getctime(self._filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
149 self.__ctime = ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
150 return self.__ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
151 ctime = property(_get_ctime)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
152
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
153 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
154 """ 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
155 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
156 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
157 if content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
158 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
159 if content_type == 'image/jpeg':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
160 output_type = 'JPEG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
161 elif content_type == 'image/png':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
162 output_type = 'PNG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
163 elif content_type == 'image/gif':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
164 output_type = 'GIF'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
165 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
166 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
167 image = self.image
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
168 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
169 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
170 # 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
171 # 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
172 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
173 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
174 transpose_op = 1 # no change
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
175
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
176 if size is not None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
177 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
178 image.thumbnail(size, PILImage.ANTIALIAS)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
179
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
180 transpose_func = {
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
181 1: lambda image: image,
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
182 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
183 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
184 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
185 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
186 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
187 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
188 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
189 }
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
190 image = transpose_func[transpose_op](image)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
191
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
192 buf = StringIO.StringIO()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
193 image.save(buf, output_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
194 buf.flush() # XXX needed?
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
195 data = buf.getvalue()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
196 buf.close()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
197 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
198 data = ''
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
199 return content_type, data
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
200
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
201 def url(self, size=None):
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
202 """ 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
203 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
204 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
205 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
206 these class level constant sizes:
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
207 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
208 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
209 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
210 request = self.request
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
211 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
212 if size is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
213 size_str = 'orig'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
214 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
215 size_str = '%d_%d' % size
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
216 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
217 if not cache.exists(request, key):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
218 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
219 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
220 return cache.url(request, key)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
221
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
222
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
223 def macro_Image(macro, itemname=wikiutil.required_arg(unicode), width=9999, height=9999, alt=u''):
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
224 """ 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
225
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
226 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
227 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
228 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
229 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
230
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
231 <<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
232 """
266
3e4eaae2f7df add support for just giving the attachment name, fix typo
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 265
diff changeset
233 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
234 itemname = macro.formatter.page.page_name + '/' + itemname
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
235 img = Image(macro.request, itemname, alt)
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
236 return macro.formatter.image(src=img.url((width, height)), alt=img.description)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
237