Tue, Nov 6, 2012
Uploading images to our Django application can be as easy as adding an ImageField
to our model. However, ImageField
falls short in one key aspect, thumbnails. Usually when uploading images, we want to create smaller versions for them, for using in for example, galleries or previews. This however, has to be done manually using the appropriate imaging libraries available.
Enter django-thumbnail-works:
The django-thumbnail-works
package can solve this for us by providing the EnahncedImageField
class. We can easily replace all of the ImageFields
in our models with EnhancedImageFields
(which actually subclasses Django’s ImageField
), and pass the additional arguments that describe what has to be done to the image after uploading.
Here are the steps for getting django-thumbnails-works
up and running in no time.
August 2018: Please note that this post was written for an older version of Django. Changes in the code might be necessary to adapt it to the latest versions and best practices.
Installing django-thumbnail-works
should be as easy as using pip
to install the package was well as its dependencies, cropresize
and PIL
, the python imaging library.
If you’re running Ubuntu (and possibly other Linux distributions) you might notice the following disheartening message when compiling PIL
:
This is caused by the install script not being able to find the necessary development libraries and thus dropping support for the different file formats. So in order to add support to PIL
for the different imaging libraries, we need to first install the missing development libraries.
There is unfortunately another step that we have to take for the setup scripts to be able to find these libraries. If you take a look at the installation path of the different packages, you will be able to see that they were installed into the /usr/lib/i386-linux-gnu/
and /usr/lib/x86-64
directories for 32bit and 64bit systems respectively. Pip’s setup scripts expect to find the libraries inside the /lib
directory though. Fixing this is as easy as creating symlinks pointing to the correct location of the files. In order to do so, cd
into your /lib
directory:
or if you're using virtualenv:
Then link the libraries:
please remember that you may need to run these commands as root or prepend sudo to them.
Finally, reinstall the PIL
package
And now you have PIL with JPEG, ZLIB and FREETYPE2 support 😁
Adding thumbnail support should be fairly simple. The first thing that has to be done is to import from the thumbnail_works.fields_ module
the EnhancedImageField
class and replace with it all instances of the ImageField
class. Remember that since EnhancedImageField
is a subclass of ImageField
, all arguments that you may already be passing to your ImageFields
you can continue to do so.
Before continuing, we need to talk about image_processing_options
. In order to create thumbnails, we need to give our EnhancedImageField
instance a dictionary (called image_processing_options
) containing the size we want our thumbnails to be and which (if any) filters to apply.
The image_processing_options
dictionary can contain the following options:
size
: Defines what size we want the thumbnail to be. The size
option must be a string of the format widthxheight
, for example 96x128
.
format
: A string that specifies what format we want the thumbnail to be. This is of course limited to what PIL can do and with support for what it was compiled with.
upscale
: A boolean that if set will cause smaller images to be enlarged to the value specified in the size argument.
sharpen
and detail
: These boolean values enable applying the ImageFilter.SHARPEN
and the ImageFilter.DETAIL
filters respectively.
With that out of the way, it’s time to finish editing our model. To each of the models you edited earlier, there’s two arguments you can pass. The first one is the process_source
argument which defines how you want the original image to processed before it is saved. If you want to leave the image as is, just skip this argument. If you want to do any processing, pass an image_processing_options
dictionary. The second argument is the thumbnails dictionary which should contain strings for keys representing the name of each thumbnail being generated and an `image_processing_options dictionary for each of those names.
As an example, I created the following model. When an image is uploaded it is resized to 1024 x 768 pixels and saved as a PNG file. The sharpen
and detail
filters are also applied to it. There are also three different thumbnails being generated for it. tiny
, which is just a 25 by 25 pixel image, thumb
which is a 85 by 85 pixel image with the detail
filter applied to it, and finally half
which is half the size of the original image and has the detail
and sharpen
filters applied to it.
Now that you have your thumbnails ready, all that is left is showing them off!
It is possible to access the thumbnails as fields inside the EnhangedImageField
field. Imagine we were passing our template an instance of our model called some_image
.
Accessing the original image is as easy as adding {{ some_image.image }}
to our template. Displaying the different thumbnails is as easy as displaying the image. Say I wanted to show the tiny thumbnail from my model, all I would have to do would be to add
There you have it, with django-thumbnail-works no manual work is needed, just replace your ImageField
s with EnhancedImageField
s, define how you want your thumbnails to be, and voilà!
© 2024. All rights reserved.