If you want to make changes to a single image, such as resizing or converting from one file format to another, then you'll probably load up the image in an editor and manually make the required changes. This approach is great for a single image, but it doesn't really scale past more than a few images, at which point it becomes time consuming, not to mention boring!
This is where Python and the Python Imaging Library (or PIL) come in, allowing you to write scripts that process images in batch. The PNG2GIF converter I wrote back in August is just one example of batch image processing using Python and PIL. In this post I'm going to explore some other uses, and provide lots of example code.
No matter what processing we want to do on our images the script outline will be the same: loop over all provided arguments, and perform the processing. The code to do this is shown below:
#!/usr/bin/env python import sys import Image # Loop through all provided arguments for i in range(1, len(sys.argv)): try: # Attempt to open an image file filepath = sys.argv[i] image = Image.open(filepath) except IOError, e: # Report error, and then skip to the next argument print "Problem opening", filepath, ":", e continue # Perform operations on the image here
This will allow our script to be called in all of the following ways:
batch_process.py image.gif batch_process.py image1.png image2.gif image3.jpg batch_process.py *.png batch_process.py image1.gif, *.png
With the help of PIL the image processing is really simple. Below is a collection of just some of the operations we could perform. For more details see the PIL documentation.
# Resize an image image = image.resize((width, height), Image.ANTIALIAS) # Convert to greyscale image = image.convert('L') # Blur image = image.filter(ImageFilter.BLUR) # Sharpen image = image.filter(ImageFilter.SHARPEN)
Once we've processed the image we need to save the changes. In some instances we might just want to save over the original filename. If that's the case we can just call the save method of image with its original filename. If we want to save the file under a different name, or as a different filetype we need to do a little more work:
# Split our original filename into name and extension (name, extension) = os.path.splitext(filepath) # Save with "_changed" added to the filename image.save(name + '_changed' + extension) # Save the image as a JPG image.save(name + '.jpg')
Notice in the last example how PIL takes care of the conversion to JPG for us. All we do is provide the file extension and PIL does the rest for us.
A Complete Example
Each of the steps above can easily be put together to create a batch image processing script. Below is a complete script which creates thumbnails of all provided images, and saves them as PNG images, not matter what their original format:
#!/usr/bin/env python # Batch thumbnail generation script using PIL import sys import os.path import Image thumbnail_size = (28, 28) # Loop through all provided arguments for i in range(1, len(sys.argv)): try: # Attempt to open an image file filepath = sys.argv[i] image = Image.open(filepath) except IOError, e: # Report error, and then skip to the next argument print "Problem opening", filepath, ":", e continue # Resize the image image = image.resize(thumbnail_size, Image.ANTIALIAS) # Split our original filename into name and extension (name, extension) = os.path.splitext(filepath) # Save the thumbnail as "(original_name)_thumb.png" image.save(name + '_thumb.png')