# -*- 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 """""" % ' '.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:])