# sorl-thumbnail

The sorl-thumbnail package provides an easy way to generate image thumbnails.

## Requirements

• Python 2.4+ and the Python Imaging Library (PIL).
• It does not require Django, but most features are Django specific. sorl-thumbnail should be compatible with all versions of Django (let us know if not).
• To enable PDF thumbnails you need ImageMagick
• For Word document thumbnail handling you need ImageMagick and wvWare.

## Installation

2. Put the sorl directory in your python path (I keep it in site-packages directory).
3. Include the thumbnail app in your settings.py.

Like this:

INSTALLED_APPS = (
...
'sorl.thumbnail',
)


## The {% thumbnail %} template tag

The thumbnail tag creates a thumbnail if it doesn't exist or if the source was modified more recently than the existing thumbnail. The resulting thumbnail object contains the generated thumbnail image along with some other potentially useful data. To use the sorl-thumbnail template tags you need to load them in your template:

{% load thumbnail %}


Basic tag Syntax:

{% thumbnail [source] [size] [options] %}


source must be an object where force_unicode(object) returns a path to a file relative to MEDIA_ROOT. This means an Image/FileField or string/unicode object containing the relative path to a file.

size can either be:

• the size in the format [width]x[height] (for example, {% thumbnail source 100x50 %}) or
• a variable containing a valid size (i.e. either a string in the [width]x[height] format or a tuple containing two integers): {% thumbnail source size_string %}.

### Options

Options are optional and should be a space separated.

Note to sorl-thumbnail vetarans: The older format of comma separated options is still supported (with the limitation that *quality is the only option to which you can pass an argument to).*

Unless you change the :ref:thumbnail-processors, valid options are:

crop

Crop the source image height or width to exactly match the requested thumbnail size (the default is to proportionally resize the source image to fit within the requested thumbnail size).

By default, the image is centered before being cropped. To crop from the edges, pass a comma separated string containing the x and y percentage offsets (negative values go from the right/bottom). Some examples follow:

• crop="0,0" will crop from the left and top edges.
• crop="-10,-0" will crop from the right edge (with a 10% offset) and the bottom edge.
• crop=",0" will keep the default behavior for the x axis (horizontally centering the image) and crop from the top edge.
max
Will resize the image to the same size as the crop option but it does not crop.
autocrop
Remove any unnecessary whitespace from the edges of the source image. This occurs before the crop or propotional resize.
bw
Make the thumbnail grayscale (not really just black & white).
upscale
Allow upscaling of the source image during scaling.
sharpen
Sharpen the thumbnail image (using the PIL sharpen filter)
detail
Add detail to the image, like a mild sharpen (using the PIL detail filter)
quality=[1-100]
Alter the quality of the JPEG thumbnail (the default is 85).

An example of basic usage:

<img src="{% thumbnail person.photo 80x80 crop upscale %}" />


### DjangoThumbnail class

The thumbnail tag can also place a DjangoThumbnail object in the context, providing access to the properties of the thumbnail such as the height and width:

{% thumbnail [source] [size] [options] as [variable] %}


When "as [variable]" is used, the tag does not return the absolute url of the thumbnail. The variable (containing the DjangoThumbnail object) has the following useful methods and properties:

absolute_url
The absolute url of the thumbnail (the __unicode__ method of this object also returns the absolute url, so you can also just do {{ thumbnail_variable }} in your template).
relative_url
The relative url (to MEDIA_URL) of the thumbnail.
width and height
The width/height of the thumbnail image.
filesize
The file size (in bytes) of the thumbnail. To output user-friendly file sizes, use the included :ref:filesize-filter (or Django's built-in more simplistic filesizeformat filter).
source_width and source_height
The width/height of the source image.
source_filesize
The file size of the source. Has same methods as filesize.

{% thumbnail person.photo 250x250 bw autocrop as thumb %}
<img src="{{ thumb }}" width="{{ thumb.width }}" height="{{ thumb.height }}" />


### Debugging the thumbnail tag

By default, if there is an error creating the thumbnail or resolving the image variable (1st argument) then the thumbnail tag will just return an empty string. And if there was a context variable to be set it will also be set to an empty string. For example, you will not see an error if the thumbnail could not be written to directory because of permissions error. To display those errors rather than failing silently, add a THUMBNAIL_DEBUG property to your settings module and set it to True:

THUMBNAIL_DEBUG = True


## Thumbnail filenames

The thumbnail filename is generated from the source filename, the target size, any options provided and the quality. For example, {% thumbnail "1.jpg" 80x80 crop bw %} will save the thumbnail image as:

MEDIA_ROOT + '1_jpg_80x80_bw_crop_q85.jpg'


By default, thumbnails are saved in the same directory as the source image. You can override this behaviour by adding one or more of the following properties to your settings module:

THUMBNAIL_BASEDIR
THUMBNAIL_SUBDIR
THUMBNAIL_PREFIX


Eaxmples using the tag as follows: {% thumbnail "photos/1.jpg" 150x150 %}:

# Save thumbnail images to a directory directly off MEDIA_ROOT, still
# keeping the relative directory structure of the source image.
# Result: MEDIA_ROOT + 'thumbs/photos/1_jpg_150x150_q85.jpg'
THUMBNAIL_BASEDIR = 'thumbs'

# Save thumbnail images to a sub-directory relative to the source image.
# Result: MEDIA_ROOT + 'photos/_thumbs/1_jpg_150x150_q85.jpg'
THUMBNAIL_SUBDIR = '_thumbs'

# Prepend thumnail filenames with the specified prefix.
# Result: MEDIA_ROOT + 'photos/__1_jpg_150x150_q85.jpg'
THUMBNAIL_PREFIX = '__'


## Changing the default quality and image format

If you would rather your thumbnail images have a different default JPEG quality than 85, add a THUMBNAIL_QUALITY property to your settings module. For example:

THUMBNAIL_QUALITY = 95


This will only affect images which have not be explicitly given a quality option. By default, generated thumbnails are saved as JPEG files (with the extension '.jpg').

PIL chooses which type of image to save as based on the extension so you can change the default image file type by adding a THUMBNAIL_EXTENSION property to your settings module. Note that If you change the extension, the THUMBNAIL_QUALITY will have no effect.

Example:

THUMBNAIL_EXTENSION = 'png'


## Thumbnails for other document types

PDF, EPS and PSD conversion are done with ImageMagick's convert program. The default location where sorl.thumbnail will look for this program is /usr/bin/convert.

Word documents are converted to a PostScript file with wvWare's wvps program. The default location where sorl.thumbnail will look for this program is /usr/bin/wvPS. This file is then converted to an image with ImageMagick's convert program.

To specify an alternate location for either of these programs, add the relevant property to your settings module:

THUMBNAIL_CONVERT = '/path/to/imagemagick/convert'
THUMBNAIL_WVPS = '/path/to/wvPS'


To specify which document types should be converted with ImageMagick, use the THUMBNAIL_IMAGEMAGICK_FILE_TYPES setting. The default setting is:

THUMBNAIL_IMAGEMAGICK_FILE_TYPES = ('eps', 'pdf', 'psd')


## Thumbnail Processors

By specifying a list of THUMBNAIL_PROCESSORS in your settings module, you can change (or add to) the processors which are run when you create a thumbnail. Note that the order of the processors is the order in which they are called to process the image. Each processor is passed the requested size and a dictionary containing all options which the thumbnail was called with (except for quality, because that's just used internally for saving).

For example, to add your own processor to the list of possible, you would create a processor like this:

def your_processor(image, requested_size, opts):
if 'your_option' in opts:
process_image(image)
your_processor.valid_options = ['your_option']


THUMBNAIL_PROCESSORS = (
# Default processors
'sorl.thumbnail.processors.colorspace',
'sorl.thumbnail.processors.autocrop',
'sorl.thumbnail.processors.scale_and_crop',
'sorl.thumbnail.processors.filters',
# Custom processors
'your_project.thumbnail_processors.your_processor',
)


### Default processors

colorspace
This processor is best kept at the top of the list since it will convert the image to RGB color space needed by most of following processors. It is also responsible for converting an image to grayscale if bw option is specified.
autocrop
This will crop the image of white edges and is still pretty experimental.
scale_and_crop
This will correctly scale and crop your image as indicated.
filters
This provides the sharpen and detail options described in the options section

### Writing a custom processor

A custom processor takes exactly three arguments: The image as a PIL Image Instance, the requested size as a tuple (width, hight), options as strings in a list. Your custom processor should return the processed PIL Image instance. To make sure we provide our tag with valid options and to make those available to your custom processors you have to attach a list of valid options. This is simply done by attaching a list called valid_options to your processor as described in the above example.

## Clean-up management command

The thumbnail_cleanup management command is used to delete thumbnails that no longer have an original file. Running it is simple:

./manage.py thumbnail_cleanup


### How it works

1. It will look through all your models and find ImageFields, then from the upload_to argument to that it will find all thumbnails.
2. If then in turn the thumbnail exists but not the original file, it will delete the thumbnail.

### Limitations

• It will not even try to delete thumbnails in date formatted directories.
• There can occur name collisions if a file name matches that of a potential thumbnail (see thumb_re).

## Thumbnail Fields

Two field classes (based on Django's ImageField) are provided for use in your Django models. They can be imported from sorl.thumbnail.fields.

• ThumbnailField resizes the source image before saving.
• ImageWithThumbnailsField keeps the original source image but provides an easy interface for accessing a predefined thumbnail.

Both fields also allow for :ref:multiple-thumbnails, and when the source image is deleted, any related thumbnails are also automatically deleted.

### ThumbnailField

size (required)
A 2-length tuple used to size down the width and height of the source image.
options
A list of options to use when thumbnailing the source image.
quality
Alter the quality of the JPEG thumbnail.
basedir, subdir and prefix
Used to override the default :ref:thumbnail-filenames settings.

Here is an example model with a ThumbnailField:

MyModel(models.Model):
name = models.TextField(max_length=50)


### ImageWithThumbnailsField

A thumbnail argument is required for this field. Pass in a dictionary with the following values (all optional except for size):

size
A 2-length tuple of the thumbnail width and height.
options
A list of options for this thumbnail.
quality, basedir, subdir and prefix
Used to override the default :ref:thumbnail-filenames settings.

Your model instance's field will have a new property, thumbnail, which returns a DjangoThumbnail instance for your pleasure (if you use this in a template, it'll return the full URL to the thumbnail).

Let's look at an example. Here is a model with an ImageWithThumbnailsField:

MyModel(models.Model):
name = models.TextField(max_length=50)
thumbnail={'size': (50, 50)})


A template (passed an instance of MyModel) would simply use something like: <img src="{{ my_model.photo.thumbnail }}" alt="{{ my_model.name }}" /> or it could use the :ref:simple-html-tag.

### Simple HTML tag

Your model instance's field (for both thumbnail field types) has a new thumbnail_tag property which can be used to return HTML like <img src="..." width="..." height="..." alt="" />.

Now, even simpler for just a basic img tag: {{ my_model.photo.thumbnail_tag }}.

Note that when the source image is deleted, any related thumbnails are also automatically deleted.

### Multiple Thumbnails

If you want to use multiple thumbnails for a single field, you can use the extra_thumbnails argument, passing it a dictionary like so:

photo = ImageWithThumbnailsField(
thumbnail={'size': (50, 50)},
extra_thumbnails={
'icon': {'size': (16, 16), 'options': ['crop', 'upscale']},
'large': {'size': (200, 400)},
},
)


This would allow you to access the extra thumbnails like this: my_model.photo.extra_thumbnails['icon'] (or in a template, {{ my_model.photo.extra_thumbnails.icon }}).

This is available to both thumbnail field types.

Similar to how the :ref:simple-html-tag works, you can using the extra_thumbnails_tag property: my_model.photo.extra_thumbnails_tag['large'] (or in a template, {{ my_model.photo.extra_thumbnails_tag.large }}).

### When thumbnails are generated

The normal behaviour is that thumbnails are only generated when they are first accessed. To have them generated as soon as the source image is saved, you can set the field's generate_on_save attribute to True.

### Changing the thumbnail tag HTML

If you don't like the default HTML output by the thumbnail tag shortcuts provided by this field, you can use the thumbnail_tag argument. For example, to use HTML4.0 compliant tags, you would do the following:

photo = ImageWithThumbnailsField(
thumbnail={'size': (50, 50)},
template_tag='<img src="%(src)s" width="%(width)s" height="%(height)s">'
)


### Generate a different image type than JPEG

PIL chooses which type of image to save as based on the extension so you can use the extension argument to save as a different image type that the default JPEG format. For example, to make the generated thumbnail a PNG file:

photo = ImageWithThumbnailsField(
thumbnail={'size': (50, 50), 'extension': 'png'}
)
avatar = ThumbnailField(
size=(50, 50),
extension='png'
)


## This just doesn't cover my cravings!

1. Use the DjangoThumbnail class in sorl.thumbnail.main if you want behaviour similar to :ref:template-tag. If you want to use a different file naming method, just subclass and override the _get_relative_thumbnail method.
2. Go for the Thumbnail class in sorl.thumbnail.base for more low-level creation of thumbnails. This class doesn't have any Django-specific ties.

## Filesize filter

This filter returns the number of bytes in either the nearest unit or a specific unit (depending on the chosen format method). Use this filter to output user-friendly file sizes. For example:

{% thumbnail source 200x200 as thumb %}
Thumbnail file size: {{ thumb.filesize|filesize }}


If the generated thumbnail size came to 2000 bytes, this would output "Thumbnail file size: 1.9 KiB" (the filter's default format is auto1024). You can specify a different format like so:

{{ thumb.filesize|filesize:"auto1000long" }}


Which would output "2 kilobytes".

Acceptable formats are:

auto1024, auto1000
convert to the nearest unit, appending the abbreviated unit name to the string (e.g. '2 KiB' or '2 kB'). auto1024 is the default format.
auto1024long, auto1000long
convert to the nearest multiple of 1024 or 1000, appending the correctly pluralized unit name to the string (e.g. '2 kibibytes' or '2 kilobytes').
kB, MB, GB, TB, PB, EB, ZB, YB
convert to the exact unit (using multiples of 1000).
KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB
convert to the exact unit (using multiples of 1024).

The auto1024 and auto1000 formats return a string, appending the correct unit to the value. All other formats return the floating point value.