summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mcrute@gmail.com>2015-05-18 20:25:46 -0700
committerMike Crute <mcrute@gmail.com>2015-05-18 20:25:46 -0700
commit4aaa43a0ad9ff683668c141f5f26a51612de2152 (patch)
treecf51ea9cf2e1b10e3c712cfe0093f722e90cb9ae
downloadmoin_thumbnail-4aaa43a0ad9ff683668c141f5f26a51612de2152.tar.bz2
moin_thumbnail-4aaa43a0ad9ff683668c141f5f26a51612de2152.tar.xz
moin_thumbnail-4aaa43a0ad9ff683668c141f5f26a51612de2152.zip
Initial importHEADmaster
-rw-r--r--.gitignore3
-rw-r--r--setup.py35
-rw-r--r--thumbnail/__init__.py4
-rw-r--r--thumbnail/action/Thumbnail.py140
-rw-r--r--thumbnail/action/__init__.py5
-rw-r--r--thumbnail/macro/Thumbnail.py40
-rw-r--r--thumbnail/macro/ThumbnailGallery.py47
-rw-r--r--thumbnail/macro/__init__.py5
8 files changed, 279 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b116e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
1/*.egg-info
2*.pyc
3.DS_Store
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..dddb52c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,35 @@
1from setuptools import setup, find_packages
2
3setup(
4 name="CruteMoinThumbnail",
5 version="1.0",
6 description="",
7 author="Michael Crute <mcrute@gmail.com>",
8 license="MIT",
9 packages=find_packages(),
10 entry_points={
11 "moin.plugins.action": [
12 "Thumbnail = thumbnail.action.Thumbnail:execute",
13 ],
14# "moin.plugins.converter": [
15# ],
16# "moin.plugins.events": [
17# ],
18# "moin.plugins.filter": [
19# ],
20# "moin.plugins.formatter": [
21# ],
22 "moin.plugins.macro": [
23 "Thumbnail = thumbnail.macro.Thumbnail:macro_Thumbnail",
24 "ThumbnailGallery = thumbnail.macro.ThumbnailGallery:macro_ThumbnailGallery",
25 ],
26# "moin.plugins.parser": [
27# ],
28# "moin.plugins.theme": [
29# ],
30# "moin.plugins.userprefs": [
31# ],
32# "moin.plugins.xmlrpc": [
33# ],
34 }
35)
diff --git a/thumbnail/__init__.py b/thumbnail/__init__.py
new file mode 100644
index 0000000..f2d8200
--- /dev/null
+++ b/thumbnail/__init__.py
@@ -0,0 +1,4 @@
1# *** Do not remove this! ***
2# Although being empty, the presence of this file is important for plugins
3# working correctly.
4
diff --git a/thumbnail/action/Thumbnail.py b/thumbnail/action/Thumbnail.py
new file mode 100644
index 0000000..3ff1f42
--- /dev/null
+++ b/thumbnail/action/Thumbnail.py
@@ -0,0 +1,140 @@
1import os
2import hashlib
3from PIL import Image, ImageOps
4from PIL.ImageFileIO import ImageFileIO
5
6from MoinMoin import log
7from MoinMoin import wikiutil
8from MoinMoin.Page import Page
9from MoinMoin.action import AttachFile
10from MoinMoin.caching import CacheEntry
11
12
13logging = log.getLogger(__name__)
14
15
16def crop(img, width, height):
17 src_width, src_height = img.size
18 src_ratio = float(src_width) / float(src_height)
19 dst_width, dst_height = int(width), int(height)
20 dst_ratio = float(dst_width) / float(dst_height)
21
22 if dst_ratio < src_ratio:
23 crop_height = src_height
24 crop_width = crop_height * dst_ratio
25 x_offset = float(src_width - crop_width) / 2
26 y_offset = 0
27 else:
28 crop_width = src_width
29 crop_height = crop_width / dst_ratio
30 x_offset = 0
31 y_offset = float(src_height - crop_height) / 3
32
33 return img.crop((
34 x_offset,
35 y_offset,
36 x_offset + int(crop_width),
37 y_offset + int(crop_height)
38 ))
39
40
41def thumbnail(img, long_side):
42 long_side = int(long_side)
43 width, height = [float(d) for d in img.size]
44
45 if height > width:
46 width = (width / height) * long_side
47 height = long_side
48 else:
49 height = (height / width) * long_side
50 width = long_side
51
52 img.thumbnail((width, height), Image.ANTIALIAS)
53 return img
54
55
56def thumbnail_constrain(img, size, dimension):
57 size = int(size)
58 width, height = [float(d) for d in img.size]
59
60 if dimension.lower() == "h":
61 height, width = size, ((width * size) / height)
62 elif dimension.lower() == "w":
63 width, height = size, ((height * size) / width)
64 else:
65 raise Exception("Must contrain valid dimension")
66
67 img.thumbnail((int(width), int(height)), Image.ANTIALIAS)
68 return img
69
70
71def get_cache_key(request, filename):
72 ops = hashlib.md5(":".join(request.values.getlist("do")))
73
74 key = filename.split(".")
75 key.insert(0, "thumbnail")
76 key.insert(-1, ops.hexdigest()[:8])
77
78 return ".".join(key)
79
80
81def execute(pagename, request):
82 _ = request.getText
83
84 if not request.user.may.read(pagename):
85 return _('You are not allowed to view attachments of this page.')
86
87 page = Page(request, pagename)
88 pagename, filename, fpath = AttachFile._access_file(pagename, request)
89
90 if not filename:
91 request.status_code = 404
92 return
93
94 cache = CacheEntry(request, page,
95 get_cache_key(request, filename), scope="item")
96
97 if cache.exists() and (cache.mtime() >= os.path.getmtime(fpath)):
98 logging.info("Using cache for %s", fpath)
99 cache.open(mode="r")
100 request.write(cache.read())
101 cache.close()
102 return
103
104 action_map = {
105 'ds': ImageOps.grayscale,
106 'cr': crop,
107 'th': thumbnail,
108 'tc': thumbnail_constrain,
109 }
110
111 with open(fpath) as fp:
112 img = Image.open(fp)
113
114 for action in request.values.getlist("do"):
115 action = action.split(":")
116 args = action[1].split(",") if len(action) > 1 else []
117
118 try:
119 img = action_map[action[0]](img, *args)
120 except Exception, e:
121 request.status_code = 400
122 request.write("Error: {}".format(e))
123 return
124
125 mt = wikiutil.MimeType(filename=filename)
126 request.headers['Content-Type'] = mt.content_type()
127 data = img.tostring('jpeg', img.mode)
128
129 try:
130 cache.lock("w")
131 cache.open(mode="w")
132 cache.write(data)
133 cache.close()
134 except Exception, e:
135 request.status_code = 500
136 request.write("Error: {}".format(e))
137 return
138 finally:
139 cache.unlock()
140 request.write(data)
diff --git a/thumbnail/action/__init__.py b/thumbnail/action/__init__.py
new file mode 100644
index 0000000..e4ed3b6
--- /dev/null
+++ b/thumbnail/action/__init__.py
@@ -0,0 +1,5 @@
1# -*- coding: iso-8859-1 -*-
2
3from MoinMoin.util import pysupport
4
5modules = pysupport.getPackageModules(__file__)
diff --git a/thumbnail/macro/Thumbnail.py b/thumbnail/macro/Thumbnail.py
new file mode 100644
index 0000000..0603435
--- /dev/null
+++ b/thumbnail/macro/Thumbnail.py
@@ -0,0 +1,40 @@
1from MoinMoin import wikiutil
2from MoinMoin.action import AttachFile
3
4
5def macro_Thumbnail(macro, attachment, height=200, width=None, link=True):
6 _ = macro.request.getText
7 formatter = macro.formatter
8
9 pagename, filename = AttachFile.absoluteName(attachment, formatter.page.page_name)
10 fname = wikiutil.taintfilename(filename)
11
12 if not macro.request.user.may.read(pagename):
13 return _('You are not allowed to view attachments of this page.')
14
15 if width:
16 size, dimension = width, "w"
17 else:
18 size, dimension = height, "h"
19
20 if AttachFile.exists(macro.request, pagename, fname):
21 url = AttachFile.getAttachUrl(pagename, fname, macro.request, do='get')
22
23 output = [
24 formatter.url(True, url) if link else "",
25 formatter.image(
26 macro.request.href(pagename, {
27 "target": fname,
28 "action": "Thumbnail",
29 "do": "tc:{},{}".format(size, dimension)
30 })),
31 formatter.url(False) if link else "",
32 ]
33 else:
34 output = [
35 formatter.span(True, style="color: red"),
36 "No Image: {}".format(attachment),
37 formatter.span(False),
38 ]
39
40 return "".join(output)
diff --git a/thumbnail/macro/ThumbnailGallery.py b/thumbnail/macro/ThumbnailGallery.py
new file mode 100644
index 0000000..038c3bc
--- /dev/null
+++ b/thumbnail/macro/ThumbnailGallery.py
@@ -0,0 +1,47 @@
1import re
2from MoinMoin import wikiutil
3from MoinMoin.action import AttachFile
4
5
6def macro_ThumbnailGallery(macro, page=None, regex=None, height=200, width=None, link=True):
7 _ = macro.request.getText
8 formatter = macro.formatter
9 pagename = page or macro.formatter.page.page_name
10 output = []
11
12 if not regex:
13 regex = re.compile(".*\.(jpg|jpeg|png|gif)$")
14 else:
15 regex = re.compile(regex)
16
17 if not macro.request.user.may.read(pagename):
18 return _('You are not allowed to view attachments of this page.')
19
20 for attachment in AttachFile._get_files(macro.request, pagename):
21 if regex.match(attachment) is None:
22 continue
23
24 pagename, filename = AttachFile.absoluteName(attachment, pagename)
25 fname = wikiutil.taintfilename(filename)
26
27 if width:
28 size, dimension = width, "w"
29 else:
30 size, dimension = height, "h"
31
32 if AttachFile.exists(macro.request, pagename, fname):
33 url = AttachFile.getAttachUrl(pagename, fname, macro.request, do='get')
34
35 output.extend([
36 macro.formatter.url(True, url) if link else "",
37 macro.formatter.image(
38 macro.request.href(pagename, {
39 "target": fname,
40 "action": "Thumbnail",
41 "do": "tc:{},{}".format(size, dimension)
42 })),
43 macro.formatter.url(False) if link else "",
44 " ",
45 ])
46
47 return "".join(output)
diff --git a/thumbnail/macro/__init__.py b/thumbnail/macro/__init__.py
new file mode 100644
index 0000000..e4ed3b6
--- /dev/null
+++ b/thumbnail/macro/__init__.py
@@ -0,0 +1,5 @@
1# -*- coding: iso-8859-1 -*-
2
3from MoinMoin.util import pysupport
4
5modules = pysupport.getPackageModules(__file__)