1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 | # -*- coding: utf-8 -*-
"""
django templates tags for images
@author: R. BECK
@version: 0.1
"""
#from __future__ import with_statement #Python 2.5
import base64
import os
import Image
from re import compile as compile_re
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from django.conf import settings
from django.template import TemplateSyntaxError, Node, Library, Template
register = Library()
TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG
MEDIA_ROOT = settings.MEDIA_ROOT
CACHE_DIR = "/tmp"
templatevar_re = compile_re("\{\{(.+)\}\}")
media_re = compile_re("\{\{MEDIA_ROOT|MEDIA_URL\}\}")
class EmbeddedImgNode(Node):
"""Image node parser for rendering html inline base64 image"""
def __init__(self, attributes):
self.attrs = {}
attrs = self.attrs
for attr_value in attributes:
try:
attr, value = attr_value.split('=', 1)
except ValueError, val_err:
raise TemplateSyntaxError(u"Syntax Error :", val_err)
attrs[attr] = value
src = attrs.get('src')
if not src:
raise TemplateSyntaxError(u"You have to specify a non-empty src \
attribute")
def _encode_img(self, file_path):
"""Returns image base64 string representation and makes a cache file"""
filename = file_path.rpartition(os.sep)[2]
need_cache = True
content = ""
cache_file = "%s_cache" % os.path.join(CACHE_DIR, filename)
try:
with open(cache_file, 'r') as cached_file:
content = cached_file.read()
need_cache = False
except IOError:
pass
if need_cache:
try:
image = open(file_path, 'r')
out = StringIO()
base64.encode(image, out)
content = out.getvalue().replace('\n', '')
except IOError:
pass
else:
try:
with open(cache_file, 'w+') as cached_file:
cached_file.write(content)
except IOError:
pass
return content
def _render_img(self):
"""Prepare image attributes"""
attrs = self.attrs
attrs_get = attrs.get
src = attrs_get('src')
height = attrs_get('height')
width = attrs_get('width')
if media_re.search(src):
src = src.replace('{{MEDIA_ROOT}}', '') \
.replace('{{MEDIA_URL}}', '')
src = src.replace('"', '')
src = os.path.join(MEDIA_ROOT, src)
try:
img = Image.open(src)
_width, _height = img.size
_format = 'image/%s' % img.format
if not height:
attrs['height'] = '%spx' % _height
if not width:
attrs['width'] = '%spx' % _width
b64encoded = self._encode_img(img.filename)
attrs['src'] = "data:%s;base64,%s" % (_format, b64encoded)
except IOError:
attrs['src'] = ""
def render(self, context):
self._render_img()
attrs = self.attrs
search = templatevar_re.search
for k, v in attrs.iteritems():
if search(v):
attrs[k] = Template(v).render(context)
return """<img %s />""" % ' '.join(['%s=%s' % (k, v if v else '""')
for k, v in attrs.iteritems()])
@register.tag(name="embedded_img")
def do_embedded_img(parser, token):
return EmbeddedImgNode(token.split_contents()[1:])
|
Comments