Beispiel #1
0
def thumbnails_for_file(relative_source_path, root=None, basedir=None,
                        subdir=None, prefix=None):
    """
    Return a list of dictionaries, one for each thumbnail belonging to the
    source image.

    The following list explains each key of the dictionary:

      `filename`  -- absolute thumbnail path
      `x` and `y` -- the size of the thumbnail
      `options`   -- list of options for this thumbnail
      `quality`   -- quality setting for this thumbnail
    """
    if root is None:
        root = settings.MEDIA_ROOT
    if prefix is None:
        prefix = get_setting('PREFIX')
    if subdir is None:
        subdir = get_setting('SUBDIR')
    if basedir is None:
        basedir = get_setting('BASEDIR')
    source_dir, filename = os.path.split(relative_source_path)
    thumbs_path = os.path.join(root, basedir, source_dir, subdir)
    if not os.path.isdir(thumbs_path):
        return []
    files = all_thumbnails(thumbs_path, recursive=False, prefix=prefix,
                           subdir='')
    return files.get(filename, [])
Beispiel #2
0
def all_thumbnails(path, recursive=True, prefix=None, subdir=None):
    """
    Return a dictionary referencing all files which match the thumbnail format.

    Each key is a source image filename, relative to path.
    Each value is a list of dictionaries as explained in `thumbnails_for_file`.
    """
    if prefix is None:
        prefix = get_setting('PREFIX')
    if subdir is None:
        subdir = get_setting('SUBDIR')
    thumbnail_files = {}
    if not path.endswith('/'):
        path = '%s/' % path
    len_path = len(path)
    if recursive:
        all = os.walk(path)
    else:
        files = []
        for file in os.listdir(path):
            if os.path.isfile(os.path.join(path, file)):
                files.append(file)
        all = [(path, [], files)]
    for dir_, subdirs, files in all:
        rel_dir = dir_[len_path:]
        for file in files:
            thumb = re_thumbnail_file.match(file)
            if not thumb:
                continue
            d = thumb.groupdict()
            source_filename = d.pop('source_filename')
            if prefix:
                source_path, source_filename = os.path.split(source_filename)
                if not source_filename.startswith(prefix):
                    continue
                source_filename = os.path.join(source_path,
                    source_filename[len(prefix):])
            d['options'] = d['options'] and d['options'].split('_') or []
            if subdir and rel_dir.endswith(subdir):
                rel_dir = rel_dir[:-len(subdir)]
            # Corner-case bug: if the filename didn't have an extension but did
            # have an underscore, the last underscore will get converted to a
            # '.'.
            m = re.match(r'(.*)_(.*)', source_filename)
            if m:
                source_filename = '%s.%s' % m.groups()
            filename = os.path.join(rel_dir, source_filename)
            thumbnail_file = thumbnail_files.setdefault(filename, [])
            d['filename'] = os.path.join(dir_, file)
            thumbnail_file.append(d)
    return thumbnail_files
Beispiel #3
0
    def render(self, context):
        # Note that this isn't a global constant because we need to change the
        # value for tests.
        raise_errors = utils.get_setting('DEBUG')
        # Get the source file.
        try:
            source = self.source_var.resolve(context)
        except VariableDoesNotExist:
            if raise_errors:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                        self.source_var)
            return self.bail_out(context)
        if not source:
            if raise_errors:
                raise TemplateSyntaxError(
                    "Variable '%s' is an invalid source." % self.source_var
                )
            return self.bail_out(context)
        # Resolve the thumbnail option values.
        try:
            opts = {}
            for key, value in self.opts.iteritems():
                if hasattr(value, 'resolve'):
                    value = value.resolve(context)
                opts[str(key)] = value
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Size variable can be either a tuple/list of two integers or a
        # valid string.
        size = opts['size']
        if isinstance(size, basestring):
            m = RE_SIZE.match(size)
            if m:
                opts['size'] = (int(m.group(1)), int(m.group(2)))
            else:
                if raise_errors:
                    raise TemplateSyntaxError("%r is not a valid size." % size)
                return self.bail_out(context)
        # Ensure the quality is an integer.
        if 'quality' in opts:
            try:
                opts['quality'] = int(opts['quality'])
            except (TypeError, ValueError):
                if raise_errors:
                    raise TemplateSyntaxError("%r is an invalid quality." %
                                              opts['quality'])
                return self.bail_out(context)

        try:
            thumbnail = get_thumbnailer(source).get_thumbnail(opts)
        except Exception, e:
            if raise_errors:
                raise TemplateSyntaxError(u"Couldn't get the thumbnail %s: %s" %
                                          (source, e))
            return self.bail_out(context)
Beispiel #4
0
    def render(self, context):
        # Note that this isn't a global constant because we need to change the
        # value for tests.
        raise_errors = utils.get_setting('DEBUG')
        # Get the source file.
        try:
            source = self.source_var.resolve(context)
        except VariableDoesNotExist:
            if raise_errors:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                        self.source_var)
            return self.bail_out(context)
        # Resolve the thumbnail option values.
        try:
            opts = {}
            for key, value in self.opts.iteritems():
                if hasattr(value, 'resolve'):
                    value = value.resolve(context)
                opts[str(key)] = value
        except:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Size variable can be either a tuple/list of two integers or a
        # valid string, only the string is checked.
        size = opts['size']
        if isinstance(size, basestring):
            m = RE_SIZE.match(size)
            if m:
                opts['size'] = (int(m.group(1)), int(m.group(2)))
            else:
                if raise_errors:
                    raise TemplateSyntaxError("Variable '%s' was resolved "
                            "but '%s' is not a valid size." %
                            (self.size_var, size))
                return self.bail_out(context)

        try:
            thumbnail = get_thumbnailer(source).get_thumbnail(opts)
        except:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Return the thumbnail file url, or put the file on the context.
        if self.context_name is None:
            return escape(thumbnail.url)
        else:
            context[self.context_name] = thumbnail
            return ''
Beispiel #5
0
from django.core.files.base import File, ContentFile
from django.core.files.storage import get_storage_class, default_storage, \
    Storage
from django.db.models.fields.files import ImageFieldFile, FieldFile
from django.utils.html import escape
from django.utils.safestring import mark_safe
from easy_thumbnails import engine, models, utils
import datetime
import os
from django.utils.http import urlquote

DEFAULT_THUMBNAIL_STORAGE = get_storage_class(
    utils.get_setting('DEFAULT_STORAGE'))()


def get_thumbnailer(object, relative_name=None):
    """
    Get a :class:`Thumbnailer` for a source file.

    The ``object`` argument is usually either one of the following:

        * ``FieldFile`` instance (i.e. a model instance file/image field
          property). 

        * ``File`` or ``Storage`` instance, and for both of these cases the
          ``relative_name`` argument must also be provided

        * A string, which will be used as the relative name (the source will be
          set to the default storage)

    For rarer needed cases, it can also be one of the following:
Beispiel #6
0
try:
    from PIL import Image
except ImportError:
    import Image
from easy_thumbnails import utils
import os
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

DEFAULT_PROCESSORS = [
    utils.dynamic_import(p) for p in utils.get_setting('PROCESSORS')
]

SOURCE_GENERATORS = [
    utils.dynamic_import(p) for p in utils.get_setting('SOURCE_GENERATORS')
]


def process_image(source, processor_options, processors=None):
    """
    Process a source PIL image through a series of image processors, returning
    the (potentially) altered image.
    """
    if processors is None:
        processors = DEFAULT_PROCESSORS
    image = source
    for processor in processors:
        image = processor(image, **processor_options)
    return image
Beispiel #7
0
try:
    from PIL import Image
except ImportError:
    import Image
from easy_thumbnails import utils
import os
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


DEFAULT_PROCESSORS = [utils.dynamic_import(p)
                      for p in utils.get_setting('PROCESSORS')]


def process_image(source, processor_options, processors=None):
    """
    Process a source PIL image through a series of image processors, returning
    the (potentially) altered image.
    
    """
    if processors is None:
        processors = DEFAULT_PROCESSORS
    image = source
    for processor in processors:
        image = processor(image, **processor_options)
    return image


def save_image(image, destination=None, filename=None, **options):
Beispiel #8
0
try:
    from PIL import Image
except ImportError:
    import Image
from easy_thumbnails import utils
import os

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


DEFAULT_PROCESSORS = [utils.dynamic_import(p) for p in utils.get_setting("PROCESSORS")]

SOURCE_GENERATORS = [utils.dynamic_import(p) for p in utils.get_setting("SOURCE_GENERATORS")]


def process_image(source, processor_options, processors=None):
    """
    Process a source PIL image through a series of image processors, returning
    the (potentially) altered image.
    
    """
    if processors is None:
        processors = DEFAULT_PROCESSORS
    image = source
    for processor in processors:
        image = processor(image, **processor_options)
    return image
Beispiel #9
0
try:
    from PIL import Image
except ImportError:
    import Image
from easy_thumbnails import utils
import os
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


DEFAULT_PROCESSORS = [utils.dynamic_import(p)
                      for p in utils.get_setting('PROCESSORS')]

SOURCE_GENERATORS = [utils.dynamic_import(p)
                     for p in utils.get_setting('SOURCE_GENERATORS')]


def process_image(source, processor_options, processors=None):
    """
    Process a source PIL image through a series of image processors, returning
    the (potentially) altered image.
    """
    if processors is None:
        processors = DEFAULT_PROCESSORS
    image = source
    for processor in processors:
        image = processor(image, **processor_options)
    return image
Beispiel #10
0
 def __init__(self, location=None, base_url=None, *args, **kwargs):
     location = utils.get_setting('MEDIA_ROOT', override=location) or None
     base_url = utils.get_setting('MEDIA_URL', override=base_url) or None
     super(ThumbnailFileSystemStorage,
           self).__init__(location, base_url, *args, **kwargs)
def get_thumbnail_path(path):
    basedir = get_setting('BASEDIR')
    subdir = get_setting('SUBDIR')
    return os.path.join(basedir, path, subdir)
import os
import re
from django.db import models
from django.conf import settings
from django.core.management.base import NoArgsCommand
from easy_thumbnails.utils import get_setting

try:
    set
except NameError:
    from sets import Set as set  # For Python 2.3

thumb_re = re.compile(r'^%s(.*)_\d{1,}x\d{1,}_[-\w]*q([1-9]\d?|100)\.jpg' %
                      get_setting('PREFIX'))


def get_thumbnail_path(path):
    basedir = get_setting('BASEDIR')
    subdir = get_setting('SUBDIR')
    return os.path.join(basedir, path, subdir)


def clean_up():
    paths = set()
    for app in models.get_apps():
        model_list = models.get_models(app)
        for model in model_list:
            for field in model._meta.fields:
                if isinstance(field, models.ImageField):
                    #TODO: take care of date formatted and callable upload_to.
                    if (not callable(field.upload_to)
def get_thumbnail_path(path):
    basedir = get_setting('BASEDIR')
    subdir = get_setting('SUBDIR')
    return os.path.join(basedir, path, subdir)
import os
import re
from django.db import models
from django.conf import settings
from django.core.management.base import NoArgsCommand
from easy_thumbnails.utils import get_setting

try:
    set
except NameError:
    from sets import Set as set     # For Python 2.3

thumb_re = re.compile(r'^%s(.*)\.\d{1,}x\d{1,}_[-\w]*q([1-9]\d?|100)\.jpg' %
                      get_setting('PREFIX'))


def get_thumbnail_path(path):
    basedir = get_setting('BASEDIR')
    subdir = get_setting('SUBDIR')
    return os.path.join(basedir, path, subdir)


def clean_up():
    paths = set()
    for app in models.get_apps():
        model_list = models.get_models(app)
        for model in model_list:
            for field in model._meta.fields:
                if isinstance(field, models.ImageField):
                    #TODO: take care of date formatted and callable upload_to.
                    if (not callable(field.upload_to) and
Beispiel #15
0
from django.core.files.base import File, ContentFile
from django.core.files.storage import get_storage_class, default_storage, Storage
from django.db.models.fields.files import ImageFieldFile, FieldFile
from django.utils.html import escape
from django.utils.safestring import mark_safe
from easy_thumbnails import engine, models, utils
import datetime
import os
from django.utils.http import urlquote


DEFAULT_THUMBNAIL_STORAGE = get_storage_class(utils.get_setting("DEFAULT_STORAGE"))()


def get_thumbnailer(source, relative_name=None):
    """
    Get a thumbnailer for a source file.

    The ``source`` argument must be one of the following:

        * ``Thumbnailer`` instance

        * ``FieldFile`` instance (i.e. a model instance file/image field
          property)

        * ``File`` or ``Storage`` instance, and for both of these cases the
          ``relative_name`` argument must also be provided

        * A string, which will be used as the relative name (the source will be
          set to the default storage)
Beispiel #16
0
class Thumbnailer(File):
    """
    A file-like object which provides some methods to generate thumbnail
    images.

    You can subclass this object and override the following properties to
    change the defaults (pulled from the default settings):

        * thumbnail_basedir
        * thumbnail_subdir
        * thumbnail_prefix
        * thumbnail_quality
        * thumbnail_extension
        * source_generators
        * thumbnail_processors
    """
    thumbnail_basedir = utils.get_setting('BASEDIR')
    thumbnail_subdir = utils.get_setting('SUBDIR')
    thumbnail_prefix = utils.get_setting('PREFIX')
    thumbnail_quality = utils.get_setting('QUALITY')
    thumbnail_extension = utils.get_setting('EXTENSION')
    thumbnail_transparency_extension = utils.get_setting(
                                                    'TRANSPARENCY_EXTENSION')
    source_generators = None
    thumbnail_processors = None

    def __init__(self, file, name=None, source_storage=None,
                 thumbnail_storage=None, *args, **kwargs):
        super(Thumbnailer, self).__init__(file, name, *args, **kwargs)
        self.source_storage = source_storage or default_storage
        self.thumbnail_storage = (thumbnail_storage or
                                  DEFAULT_THUMBNAIL_STORAGE)

    def generate_thumbnail(self, thumbnail_options):
        """
        Return an unsaved ``ThumbnailFile`` containing a thumbnail image.

        The thumbnail image is generated using the ``thumbnail_options``
        dictionary.
        """
        image = engine.generate_source_image(self, thumbnail_options,
                                             self.source_generators)
        if image is None:
            raise exceptions.InvalidImageFormatError(
                "The source file does not appear to be an image")

        thumbnail_image = engine.process_image(image, thumbnail_options,
                                               self.thumbnail_processors)
        quality = thumbnail_options.get('quality', self.thumbnail_quality)

        filename = self.get_thumbnail_name(thumbnail_options,
                            transparent=self.is_transparent(thumbnail_image))

        data = engine.save_image(thumbnail_image, filename=filename,
                                 quality=quality).read()

        thumbnail = ThumbnailFile(filename, ContentFile(data),
                                  storage=self.thumbnail_storage)
        thumbnail.image = thumbnail_image
        thumbnail._committed = False

        return thumbnail

    def get_thumbnail_name(self, thumbnail_options, transparent=False):
        """
        Return a thumbnail filename for the given ``thumbnail_options``
        dictionary and ``source_name`` (which defaults to the File's ``name``
        if not provided).
        """
        path, source_filename = os.path.split(self.name)
        source_extension = os.path.splitext(source_filename)[1][1:]
        filename = '%s%s' % (self.thumbnail_prefix, source_filename)
        if transparent:
            extension = self.thumbnail_transparency_extension
        else:
            extension = self.thumbnail_extension
        extension = extension or 'jpg'

        thumbnail_options = thumbnail_options.copy()
        size = tuple(thumbnail_options.pop('size'))
        quality = thumbnail_options.pop('quality', self.thumbnail_quality)
        initial_opts = ['%sx%s' % size, 'q%s' % quality]

        opts = thumbnail_options.items()
        opts.sort()   # Sort the options so the file name is consistent.
        opts = ['%s' % (v is not True and '%s-%s' % (k, v) or k)
                for k, v in opts if v]

        all_opts = '_'.join(initial_opts + opts)

        data = {'opts': all_opts}
        basedir = self.thumbnail_basedir % data
        subdir = self.thumbnail_subdir % data

        filename_parts = [filename]
        if ('%(opts)s' in self.thumbnail_basedir or
            '%(opts)s' in self.thumbnail_subdir):
            if extension != source_extension:
                filename_parts.append(extension)
        else:
            filename_parts += [all_opts, extension]
        filename = '.'.join(filename_parts)

        return os.path.join(basedir, path, subdir, filename)

    def get_thumbnail(self, thumbnail_options, save=True):
        """
        Return a ``ThumbnailFile`` containing a thumbnail.

        It the file already exists, it will simply be returned.

        Otherwise a new thumbnail image is generated using the
        ``thumbnail_options`` dictionary. If the ``save`` argument is ``True``
        (default), the generated thumbnail will be saved too.
        """
        opaque_name = self.get_thumbnail_name(thumbnail_options,
                                              transparent=False)
        transparent_name = self.get_thumbnail_name(thumbnail_options,
                                                   transparent=True)
        if opaque_name == transparent_name:
            names = (opaque_name,)
        else:
            names = (opaque_name, transparent_name)
        for filename in names:
            if self.thumbnail_exists(filename):
                thumbnail = ThumbnailFile(name=filename,
                                          storage=self.thumbnail_storage)
                return thumbnail

        thumbnail = self.generate_thumbnail(thumbnail_options)
        if save:
            save_thumbnail(thumbnail, self.thumbnail_storage)
            # Ensure the right thumbnail name is used based on the transparency
            # of the image.
            filename = (self.is_transparent(thumbnail.image) and
                        transparent_name or opaque_name)
            self.get_thumbnail_cache(filename, create=True, update=True)

        return thumbnail

    def thumbnail_exists(self, thumbnail_name):
        """
        Calculate whether the thumbnail already exists and that the source is
        not newer than the thumbnail.

        If both the source and thumbnail file storages are local, their
        file modification times are used. Otherwise the database cached
        modification times are used.
        """
        # Try to use the local file modification times first.
        source_modtime = self.get_source_modtime()
        thumbnail_modtime = self.get_thumbnail_modtime(thumbnail_name)
        # The thumbnail modification time will be 0 if there was an OSError,
        # in which case it will still be used (but always return False).
        if source_modtime and thumbnail_modtime is not None:
            return thumbnail_modtime and source_modtime <= thumbnail_modtime
        # Fall back to using the database cached modification times.
        source = self.get_source_cache()
        if not source:
            return False
        thumbnail = self.get_thumbnail_cache(thumbnail_name)
        return thumbnail and source.modified <= thumbnail.modified

    def get_source_cache(self, create=False, update=False):
        modtime = self.get_source_modtime()
        update_modified = modtime and datetime.datetime.fromtimestamp(modtime)
        if update:
            update_modified = update_modified or datetime.datetime.utcnow()
        return models.Source.objects.get_file(
            create=create, update_modified=update_modified,
            storage=self.source_storage, name=self.name)

    def get_thumbnail_cache(self, thumbnail_name, create=False, update=False):
        modtime = self.get_thumbnail_modtime(thumbnail_name)
        update_modified = modtime and datetime.datetime.fromtimestamp(modtime)
        if update:
            update_modified = update_modified or datetime.datetime.utcnow()
        source = self.get_source_cache(create=True)
        return models.Thumbnail.objects.get_file(
            create=create, update_modified=update_modified,
            storage=self.thumbnail_storage, source=source, name=thumbnail_name)

    def get_source_modtime(self):
        try:
            path = self.source_storage.path(self.name)
            return os.path.getmtime(path)
        except OSError:
            return 0
        except NotImplementedError:
            return None

    def get_thumbnail_modtime(self, thumbnail_name):
        try:
            path = self.thumbnail_storage.path(thumbnail_name)
            return os.path.getmtime(path)
        except OSError:
            return 0
        except NotImplementedError:
            return None

    def is_transparent(self, image):
        return (image.mode == 'RGBA' or
                (image.mode == 'P' and 'transparency' in image.info))
    def render(self, context):
        # Note that this isn't a global constant because we need to change the
        # value for tests.
        raise_errors = utils.get_setting('DEBUG')
        # Get the source file.
        try:
            source = self.source_var.resolve(context)
        except VariableDoesNotExist:
            if raise_errors:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                        self.source_var)
            return self.bail_out(context)
        if not source:
            if raise_errors:
                raise TemplateSyntaxError(
                    "Variable '%s' is an invalid source." % self.source_var
                )
            return self.bail_out(context)
        # Resolve the thumbnail option values.
        try:
            opts = {}
            for key, value in self.opts.iteritems():
                if hasattr(value, 'resolve'):
                    value = value.resolve(context)
                opts[str(key)] = value
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Size variable can be either a tuple/list of two integers or a
        # valid string.
        size = opts['size']
        if isinstance(size, basestring):
            m = RE_SIZE.match(size)
            if m:
                opts['size'] = (int(m.group(1)), int(m.group(2)))
            else:
                if raise_errors:
                    raise TemplateSyntaxError("%r is not a valid size." % size)
                return self.bail_out(context)
        # Ensure the quality is an integer.
        if 'quality' in opts:
            try:
                opts['quality'] = int(opts['quality'])
            except (TypeError, ValueError):
                if raise_errors:
                    raise TemplateSyntaxError("%r is an invalid quality." %
                                              opts['quality'])
                return self.bail_out(context)

        # first try to get the thumbnail url from cache, if it is available
        # just return it otherwise create the thumb
        if isinstance(source, basestring):
            relname = source
        elif isinstance(source, FieldFile):
            relname = source.name
        else:
            relname = str(source)

        opt_str = ""
        for key in opts.keys():
            opt_str += "{0}_{1}".format(key, opts[key])

        cache_key = "{0}{1}".format(relname, opt_str)
        cache_key = escape(cache_key).replace(" ", "_").replace("(", "").\
                    replace(")", "").replace(",","")
        cache_key = str(hash(cache_key))
        thumb_url = False
        if thumb_url:
            if not self.context_name:
                return thumb_url
        # if the thumb is not cached create one and cache it
        try:
            thumbnail = get_thumbnailer(source).get_thumbnail(opts)
        except Exception:
            if raise_errors:
                raise
            result = self.bail_out(context)
            #cache.set(cache_key, result, TIMEOUT_CACHE)
            return result
        # Return the thumbnail file url, or put the file on the context.
        if self.context_name is None:
            result = escape(thumbnail.url)
            cache.set(cache_key, result, TIMEOUT_CACHE)
            return result
        else:
            context[self.context_name] = thumbnail
            return ''
Beispiel #18
0
 def __init__(self, location=None, base_url=None, *args, **kwargs):
     location = utils.get_setting('MEDIA_ROOT', override=location) or None
     base_url = utils.get_setting('MEDIA_URL', override=base_url) or None
     super(ThumbnailFileSystemStorage, self).__init__(location, base_url,
                                                      *args, **kwargs)
Beispiel #19
0
from PIL import Image
from django.core.files.base import File, ContentFile
from django.core.files.storage import get_storage_class, default_storage, \
    Storage
from django.db.models.fields.files import ImageFieldFile, FieldFile
from django.utils.html import escape
from django.utils.safestring import mark_safe
from easy_thumbnails import engine, models, utils
import datetime
import os
from django.utils.http import urlquote


DEFAULT_THUMBNAIL_STORAGE = get_storage_class(
                                        utils.get_setting('DEFAULT_STORAGE'))()


def get_thumbnailer(source, relative_name=None):
    """
    Get a thumbnailer for a source file.

    The ``source`` argument must be one of the following:

        * ``Thumbnailer`` instance

        * ``FieldFile`` instance (i.e. a model instance file/image field
          property)

        * ``File`` or ``Storage`` instance, and for both of these cases the
          ``relative_name`` argument must also be provided
Beispiel #20
0
    def render(self, context):
        # Note that this isn't a global constant because we need to change the
        # value for tests.
        raise_errors = utils.get_setting('DEBUG')
        # Get the source file.
        try:
            source = self.source_var.resolve(context)
        except VariableDoesNotExist:
            if raise_errors:
                raise VariableDoesNotExist("Variable '%s' does not exist." %
                        self.source_var)
            return self.bail_out(context)
        if not source:
            if raise_errors:
                raise TemplateSyntaxError(
                    "Variable '%s' is an invalid source." % self.source_var
                )
            return self.bail_out(context)
        # Resolve the thumbnail option values.
        try:
            opts = {}
            for key, value in self.opts.iteritems():
                if hasattr(value, 'resolve'):
                    value = value.resolve(context)
                opts[str(key)] = value
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Size variable can be either a tuple/list of two integers or a
        # valid string.
        size = opts['size']
        if isinstance(size, basestring):
            m = RE_SIZE.match(size)
            if m:
                opts['size'] = (int(m.group(1)), int(m.group(2)))
            else:
                if raise_errors:
                    raise TemplateSyntaxError("%r is not a valid size." % size)
                return self.bail_out(context)
        # Ensure the quality is an integer.
        if 'quality' in opts:
            try:
                opts['quality'] = int(opts['quality'])
            except (TypeError, ValueError):
                if raise_errors:
                    raise TemplateSyntaxError("%r is an invalid quality." %
                                              opts['quality'])
                return self.bail_out(context)

        try:
            thumbnail = get_thumbnailer(source).get_thumbnail(opts)
        except Exception:
            if raise_errors:
                raise
            return self.bail_out(context)
        # Return the thumbnail file url, or put the file on the context.
        if self.context_name is None:
            return escape(thumbnail.url)
        else:
            context[self.context_name] = thumbnail
            return ''