sorl-thumbnail

  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
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)

Comments

(Forgotten your password?)

You may use Markdown syntax here, but raw HTML will be removed.