sorl/thumbnail/templatetags/thumbnail.py:
import re, os
from django.template import Library
from sorl.thumbnail import Thumbnail
from django.conf import settings

register = Library()

@register.filter
def thumbnail_url(filename, arg=""):
    thumbnail = get_thumbnail(filename, arg)
    return thumbnail.get_url()

def get_thumbnail(filename, arg=""):

    kwargs  = {\
        'prefix': '',
        'subdir': '_thumbs',
        'size': (80,80),
        'crop': False,
        'enlarge': False,
        'quality': 75,
    }

    for a in kwargs.keys():
        if hasattr(settings, 'THUMBNAIL_%s' % a.upper()):
            kwargs.update({a: getattr(settings, 'THUMBNAIL_%s' % a.upper())})
    
    kwargs.update(filename=filename)
    
    if arg.find('crop') != -1:
        kwargs.update(crop=True)
    if arg.find('enlarge') != -1:
        kwargs.update(enlarge=True)
    quality_pat = re.compile(r'q(\d+)')
    m = quality_pat.search(arg)
    if m:
        quality = int(m.group(1))
        if quality > 0 and quality <= 100:
            kwargs.update(quality=quality)
    size_pat = re.compile(r'(\d+)x(\d+)')
    m = size_pat.search(arg)
    if m:
        kwargs.update(size=(int(m.group(1)), int(m.group(2))))

    return Thumbnail(**kwargs)



sorl/thumbnail/__init__.py:
from main import *



sorl/thumbnail/main.py:
import os, urllib
from PIL import Image
from django.conf import settings


class Thumbnail:

    def __init__(self, **kwargs):
        for k,v in kwargs.items():
            setattr(self, k, v)

        self.filename_abs = os.path.join(settings.MEDIA_ROOT, self.filename)
        self.set_thumbnail_filename()
        self.set_thumbnail()

    def __unicode__(self):
        return self.thumbnail

    def get_url(self):
        if self.thumbnail:
            return "%s%s" % (settings.MEDIA_URL, "/".join(self.thumbnail.split(os.path.sep)))
        else:
            return ""

    def set_thumbnail_filename(self):
        filehead, filetail = os.path.split(self.filename)
        basename, ext = os.path.splitext(filetail)
        thumbs_dir = os.path.join(settings.MEDIA_ROOT, filehead, self.subdir)
        if not os.path.isdir(thumbs_dir):
            os.mkdir(thumbs_dir)
        details = "%sx%s" % (self.size[0], self.size[1])
        if self.crop:
            details = "%s_%s" % (details, 'crop')
        if self.enlarge:
            details = "%s_%s" % (details, 'enlarge')
        self.thumbnail_filename = os.path.join(filehead, self.subdir, '%s%s_%s_q%s.jpg' % \
            (self.prefix, urllib.quote(basename), details, self.quality))
        self.thumbnail_filename_abs = os.path.join(settings.MEDIA_ROOT, self.thumbnail_filename)


    def set_thumbnail(self):
        if os.path.isfile(self.filename_abs):
            self.thumbnail = self.thumbnail_filename
            if os.path.isfile(self.thumbnail_filename_abs):
                if os.path.getmtime(self.filename_abs) > os.path.getmtime(self.thumbnail_filename_abs):
                    self.make_thumbnail()
            else:
                self.make_thumbnail()
        else:
            self.thumbnail = ""

    def make_thumbnail(self):
        im = Image.open(self.filename_abs)

        if im.mode not in ("L", "RGB"): 
            im = im.convert("RGB") 

        if self.crop:
            comp = max
        else:
            comp = min
        
        x, y   = float(im.size[0]), float(im.size[1])
        xr, yr = float(self.size[0]), float(self.size[1])
        r = comp(xr/x, yr/y)
        if not self.enlarge:
            r = min(r,1)
        im = im.resize([int(s*r) for s in im.size], resample=Image.ANTIALIAS)
        
        if self.crop:
            x, y   = float(im.size[0]), float(im.size[1])
            ex, ey = (x-min(x, xr))/2, (y-min(y, yr))/2
            im = im.crop((int(ex), int(ey), int(x-ex), int(y-ey)))

        try:
            im.save(self.thumbnail_filename_abs, "JPEG", quality=self.quality, optimize=1)
        except:
            im.save(self.thumbnail_filename_abs, "JPEG", quality=self.quality)


