annotate data/plugin/macro/Image.py @ 265:37b96db69d0e

MoinImage macro: renamed to Image
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sat, 13 Sep 2008 23:56:05 +0200
parents data/plugin/macro/MoinImage.py@b7e7be4340b0
children 3e4eaae2f7df
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
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
228 the original image. Thus, by not giving widht or height, you'll get the original image,
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 """
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
233 img = Image(macro.request, itemname, alt)
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
234 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
235