annotate data/plugin/macro/Image.py @ 275:2a92ddf8a7c8

Image._get_description: strip whitespae from image name
author Reimar Bauer <rb.proj AT googlemail DOT com>
date Tue, 16 Sep 2008 11:48:52 +0200
parents 1e3e876e38fb
children 03071c3569d8
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,
269
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
51 raw=None,
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
52 ):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
53 self.request = request
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
54 self.pagename, self.attachname = item_name.rsplit('/', 1)
269
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
55 self.raw = raw
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
56
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
57 # cached property values:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
58 self.__filename = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
59 self.__content_type = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
60 self.__cache_key = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
61 self.__image = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
62 self.__exif = None
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
63 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
64 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
65 self.__caption = caption
269
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
66 self.__description = self.attachname
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
67
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
68 def _get_description(self):
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
69 quotes = self.raw.split('\n')
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
70 quotes = [quote.strip() for quote in quotes]
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
71 quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
72 image_alias = self.attachname
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
73 for line in quotes:
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
74 if line.startswith('[[') and line.endswith(']]'):
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
75 img, alias = line[2:-2].split('|', 1)
275
2a92ddf8a7c8 Image._get_description: strip whitespae from image name
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 269
diff changeset
76 if img.strip() == self.attachname:
269
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
77 self.__description = alias.strip()
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
78 break
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
79 return self.__description
1e3e876e38fb moved readout of description from text_x_arnica to Image
Reimar Bauer <rb.proj AT googlemail DOT com>
parents: 267
diff changeset
80 description = property(_get_description)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
81
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
82 def _get_filename(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
83 if self.__filename is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
84 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
85 return self.__filename
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
86 _filename = property(_get_filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
87
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
88 def _get_content_type(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
89 if self.__content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
90 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
91 return self.__content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
92 content_type = property(_get_content_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
93
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
94 def _get_image(self):
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
95 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
96 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
97 return self.__image
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
98 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
99
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
100 def _get_cache_key(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
101 if self.__cache_key is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
102 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
103 return self.__cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
104 _cache_key = property(_get_cache_key)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
105
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
106 def _get_exif_data(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
107 """ 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
108 if self.__exif is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
109 key = self._cache_key
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
110 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
111 use_pickle=True, do_locking=False)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
112 if not exif_cache.exists():
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
113 # 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
114 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
115 exif_data = {}
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
116 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
117 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
118 tag_name = ExifTags.TAGS.get(tag)
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
119 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
120 exif_data[tag_name] = value
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
121 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
122 time_str = exif_data['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
123 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
124 t = time.mktime(tm)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
125 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
126 tz_str = exif_data['TimeZoneOffset']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
127 tz_offset = int(tz_str) * 3600
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
128 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
129 tz_offset = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
130 # 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
131 t -= time.timezone + tz_offset
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
132 except:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
133 t = 0
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
134 exif_data['DateTimeOriginal'] = t
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
135 except (IOError, AttributeError):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
136 exif_data = {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
137 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
138 iptc_data = {}
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
139 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
140 iptc = PILIptc.getiptcinfo(self.image) or {}
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
141 for name, key in [
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
142 ('headline', (2, 105)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
143 ('caption', (2, 120)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
144 ('copyright', (2, 116)),
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
145 ('keywords', (2, 25)), ]:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
146 try:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
147 iptc_data[name] = iptc[key]
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
148 except KeyError:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
149 pass
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
150 except:
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
151 iptc_data = {}
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
152 cache_data = (exif_data, iptc_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
153 exif_cache.update(cache_data)
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
154 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
155 else:
264
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
156 self.__exif, self.__iptc = exif_cache.content()
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
157 return self.__exif, self.__iptc
b7e7be4340b0 MoinImage: add IPTC support
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 263
diff changeset
158 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
159 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
160
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
161 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
162 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
163 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
164 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
165 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
166
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
167 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
168 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
169 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
170 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
171 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
172
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
173 def _get_ctime(self):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
174 """ 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
175 if self.__ctime is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
176 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
177 ctime = self.exif['DateTimeOriginal']
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
178 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
179 ctime = os.path.getctime(self._filename)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
180 self.__ctime = ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
181 return self.__ctime
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
182 ctime = property(_get_ctime)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
183
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
184 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
185 """ 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
186 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
187 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
188 if content_type is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
189 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
190 if content_type == 'image/jpeg':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
191 output_type = 'JPEG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
192 elif content_type == 'image/png':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
193 output_type = 'PNG'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
194 elif content_type == 'image/gif':
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
195 output_type = 'GIF'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
196 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
197 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
198 image = self.image
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
199 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
200 try:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
201 # 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
202 # 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
203 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
204 except KeyError:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
205 transpose_op = 1 # no change
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
206
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
207 if size is not None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
208 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
209 image.thumbnail(size, PILImage.ANTIALIAS)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
210
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
211 transpose_func = {
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
212 1: lambda image: image,
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
213 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
214 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
215 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
216 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
217 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
218 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
219 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
220 }
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
221 image = transpose_func[transpose_op](image)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
222
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
223 buf = StringIO.StringIO()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
224 image.save(buf, output_type)
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
225 buf.flush() # XXX needed?
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
226 data = buf.getvalue()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
227 buf.close()
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
228 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
229 data = ''
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
230 return content_type, data
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
231
263
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
232 def url(self, size=None):
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
233 """ 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
234 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
235 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
236 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
237 these class level constant sizes:
448a086d840c MoinImage: simplify API
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 262
diff changeset
238 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
239 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
240 """
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
241 request = self.request
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
242 content_type = self.content_type
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
243 if size is None:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
244 size_str = 'orig'
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
245 else:
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
246 size_str = '%d_%d' % size
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
247 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
248 if not cache.exists(request, key):
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
249 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
250 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
251 return cache.url(request, key)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
252
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
253
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
254 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
255 """ 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
256
265
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
257 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
258 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
259 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
260 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
261
37b96db69d0e MoinImage macro: renamed to Image
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 264
diff changeset
262 <<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
263 """
266
3e4eaae2f7df add support for just giving the attachment name, fix typo
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents: 265
diff changeset
264 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
265 itemname = macro.formatter.page.page_name + '/' + itemname
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
266 img = Image(macro.request, itemname, caption=alt)
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
267 return macro.formatter.image(src=img.url((width, height)), alt=img.caption)
262
c605998e1123 added MoinImage class and test macro
Thomas Waldmann <tw AT waldmann-edv DOT de>
parents:
diff changeset
268