6 re_thumbnail_file = re.compile(r'(?P<source_filename>.+)_(?P<x>\d+)x(?P<y>\d+)'
7 r'(?:_(?P<options>\w+))?_q(?P<quality>\d+)'
9 re_new_args = re.compile('(?<!quality)=')
12 def all_thumbnails(path, recursive=True, prefix=None, subdir=None):
14 Return a dictionary referencing all files which match the thumbnail format.
16 Each key is a source image filename, relative to path.
17 Each value is a list of dictionaries as explained in `thumbnails_for_file`.
19 # Fall back to using thumbnail settings. These are local imports so that
20 # there is no requirement of Django to use the utils module.
22 from sorl.thumbnail.main import get_thumbnail_setting
23 prefix = get_thumbnail_setting('PREFIX')
25 from sorl.thumbnail.main import get_thumbnail_setting
26 subdir = get_thumbnail_setting('SUBDIR')
28 if not path.endswith('/'):
35 for file in os.listdir(path):
36 if os.path.isfile(os.path.join(path, file)):
38 all = [(path, [], files)]
39 for dir_, subdirs, files in all:
40 rel_dir = dir_[len_path:]
42 thumb = re_thumbnail_file.match(file)
46 source_filename = d.pop('source_filename')
48 source_path, source_filename = os.path.split(source_filename)
49 if not source_filename.startswith(prefix):
51 source_filename = os.path.join(source_path,
52 source_filename[len(prefix):])
53 d['options'] = d['options'] and d['options'].split('_') or []
54 if subdir and rel_dir.endswith(subdir):
55 rel_dir = rel_dir[:-len(subdir)]
56 # Corner-case bug: if the filename didn't have an extension but did
57 # have an underscore, the last underscore will get converted to a
59 m = re.match(r'(.*)_(.*)', source_filename)
61 source_filename = '%s.%s' % m.groups()
62 filename = os.path.join(rel_dir, source_filename)
63 thumbnail_file = thumbnail_files.setdefault(filename, [])
64 d['filename'] = os.path.join(dir_, file)
65 thumbnail_file.append(d)
66 return thumbnail_files
69 def thumbnails_for_file(relative_source_path, root=None, basedir=None,
70 subdir=None, prefix=None):
72 Return a list of dictionaries, one for each thumbnail belonging to the
75 The following list explains each key of the dictionary:
77 `filename` -- absolute thumbnail path
78 `x` and `y` -- the size of the thumbnail
79 `options` -- list of options for this thumbnail
80 `quality` -- quality setting for this thumbnail
82 # Fall back to using thumbnail settings. These are local imports so that
83 # there is no requirement of Django to use the utils module.
85 from django.conf import settings
86 root = settings.MEDIA_ROOT
88 from sorl.thumbnail.main import get_thumbnail_setting
89 prefix = get_thumbnail_setting('PREFIX')
91 from sorl.thumbnail.main import get_thumbnail_setting
92 subdir = get_thumbnail_setting('SUBDIR')
94 from sorl.thumbnail.main import get_thumbnail_setting
95 basedir = get_thumbnail_setting('BASEDIR')
96 source_dir, filename = os.path.split(relative_source_path)
97 thumbs_path = os.path.join(root, basedir, source_dir, subdir)
98 if not os.path.isdir(thumbs_path):
100 files = all_thumbnails(thumbs_path, recursive=False, prefix=prefix,
102 return files.get(filename, [])
105 def delete_thumbnails(relative_source_path, root=None, basedir=None,
106 subdir=None, prefix=None):
108 Delete all thumbnails for a source image.
110 thumbs = thumbnails_for_file(relative_source_path, root, basedir, subdir,
112 return _delete_using_thumbs_list(thumbs)
115 def _delete_using_thumbs_list(thumbs):
117 for thumb_dict in thumbs:
118 filename = thumb_dict['filename']
128 def delete_all_thumbnails(path, recursive=True):
130 Delete all files within a path which match the thumbnails pattern.
132 By default, matching files from all sub-directories are also removed. To
133 only remove from the path directory, set recursive=False.
136 for thumbs in all_thumbnails(path, recursive=recursive).values():
137 total += _delete_using_thumbs_list(thumbs)
141 def split_args(args):
143 Split a list of argument strings into a dictionary where each key is an
146 An argument looks like ``crop``, ``crop="some option"`` or ``crop=my_var``.
147 Arguments which provide no value get a value of ``None``.
151 # Handle the old comma separated argument format.
152 if len(args) == 1 and not re_new_args.search(args[0]):
153 args = args[0].split(',')
154 # Separate out the key and value for each argument.
157 split_arg = arg.split('=', 1)
158 value = len(split_arg) > 1 and split_arg[1] or None
159 args_dict[split_arg[0]] = value
163 def image_entropy(im):
165 Calculate the entropy of an image. Used for "smart cropping".
167 hist = im.histogram()
168 hist_size = float(sum(hist))
169 hist = [h / hist_size for h in hist]
170 return -sum([p * math.log(p, 2) for p in hist if p != 0])