Some Interesting Tricks in Python Pillow

Analytics Vidhya
Published in
5 min readMar 16, 2020


Just in time snippets, python image manipulation library.

Photo by Daniel Marcinkowski on Unsplash

Image manipulation is basically a process of transforming digitised image into a desired image. Most of the times, when people think of image manipulation, photoshop is what comes to mind. It is one of the most popularly used tools out there for changing and improving images. However, this post is focused on Python image manipulation library, pillow to be exact.

According to The Hitchhiker’s Guide to Python, most image processing and manipulation techniques can be carried out effectively using two libraries: Python Imaging Library (PIL) and Open Source Computer Vision (OpenCV).

Pillow is a fork of PIL (Python Image Library), started and maintained by Alex Clark and Contributors. Originally based on the PIL code, it evolved to a better, modern and friendlier version of PIL. It supports opening and manipulating of images of many different file formats.

If you are familiar with Python Programming Language, chances are you have come across and probably used Pillow already.

Basic Installation

First, you need to have python installed on your machine. Also make sure python pip (Python Package Index) is installed and up to date. To install pillow, run the command below:

$ pip install Pillow

Now that you have installed Pillow successfully, there are some snippets below, which you might find very handy (at least I do). Note that the samples below are basic image manipulations such as resizing, blurring, grayscale conversion among others.

Convert to Grayscale (black and white)

The snippet below converts an image (test_image.jpg) to basic grayscale. Saves it as new image (test_image_grayscale.jpg).

from PIL import Image# open colour image
img ="test_image.jpg")
# convert image to black and white
img = img.convert("1")
# save new image"test_image_grayscale.jpg")
# show image in preview
Photo by Ina Sonne on Instagram

Generate a Thumbnail

Often, we need to quickly thumbnail several images. The snippets below does the trick.

from PIL import Image# open image
img ="test_image.jpg")
# set the maximum width and height for the thumbnail
max_thumbnail_size = (200, 200)
# applying size for thumbnail
# creating thumbnail"test_image_thumb.jpg")
# show image in preview
Photo by Ishan @seefromthesky on Unsplash

Replace Colour (RGB)

The code below replaces all white pixels and replaces them with yellow. More tweak is required in order to adjust images with multiple colours. Nevertheless, the snippet below works well with images with solid background colours.

from PIL import Image# open image
img ="test_image.jpg")
img = img.convert("RGB")
datas = img.getdata()new_image_data = []for item in datas:
# change all white (also shades of whites) pixels to yellow
if item[0] in list(range(190, 256)):
new_image_data.append((255, 204, 100))
# update image data
# save new image"test_image_altered_background.jpg")
# show image in preview
Image from Google Spreadsheet API

Add Borders

This accepts the colour and size of the border to be applied to the image. The border could be an integer value such as 5, which indicates all borders (left, top, right and bottom) have the same size. It Also accepts tuple i.e. (5, 10, 5, 10), each side of having a different value.

from PIL import Image, ImageOps# open image
img ="test_image.jpg")
# border color
color = "green"
# top, right, bottom, left
border = (20, 10, 20, 10)
new_img = ImageOps.expand(img, border=border, fill=color)# save new image"test_image_result.jpg")
# show new bordered image in preview

When applying a border to the image sample as above, it should look like the figure below.

Image from Google Spreadsheet API

Add Blurred Edges

This section consists of several steps in respect to the previous examples. The first part requires creating a blurred image (mask) and using that image as a mask for the original image. The steps and procedures on how to create a blurred edge image are well stated below.

from PIL import Image, ImageFilter# blur radius and diameter
radius, diameter = 20, 40
# open an image
img ="test_image.jpg")
# Paste image on white background
background_size = (img.size[0] + diameter, img.size[1] + diameter)
background ='RGB', background_size, (255, 255, 255))
background.paste(img, (radius, radius))
# create new images with white and black
mask_size = (img.size[0] + diameter, img.size[1] + diameter)
mask ='L', mask_size, 255)
black_size = (img.size[0] - diameter, img.size[1] - diameter)
black ='L', black_size, 0)
# create blur mask
mask.paste(black, (diameter, diameter))
# Blur image and paste blurred edge according to mask
blur = background.filter(ImageFilter.GaussianBlur(radius / 2))
background.paste(blur, mask=mask)"test_image_blurred.jpg", quality=100))# show blurred edged image in preview
Photo by Ina Sonne on Instagram

Add Watermarks

Using watermark is one of the oldest trick in the book used to protect image from piracy. Even though there are several new approaches to evade watermarks on images (find out if you are curious), it is still very efficient. The code sample below illustrate how to add sequential watermark across an image.

from PIL import Image, ImageDraw, ImageFont# open image to apply watermark to
img ="watermark_test.jpg")
# get image size
img_width, img_height = img.size
# 5 by 4 water mark grid
wm_size = (int(img_width * 0.20), int(img_height * 0.25))
wm_txt ="RGBA", wm_size, (255, 255, 255, 0))
# set text size, 1:40 of the image width
font_size = int(img_width / 40)
# load font e.g. gotham-bold.ttf
font = ImageFont.truetype(path.format("gotham-bold.ttf"), font_size)
d = ImageDraw.Draw(wm_txt)
wm_text = "Kuma Kum"# centralize text
left = (wm_size[0] - font.getsize(wm_text)[0]) / 2
top = (wm_size[1] - font.getsize(wm_text)[1]) / 2
# RGBA(0, 0, 0, alpha) is black
# alpha channel specifies the opacity for a colour
alpha = 75
# write text on blank wm_text image
d.text((left, top), wm_text, fill=(0, 0, 0, alpha), font=font)
# uncomment to rotate watermark text
# wm_txt = wm_txt.rotate(15, expand=1)
# wm_txt = wm_txt.resize(wm_size, Image.ANTIALIAS)
for i in range(0, img_width, wm_txt.size[0]):
for j in range(0, img_height, wm_txt.size[1]):
img.paste(wm_txt, (i, j), wm_txt)
# save image with watermark"watermark-image.jpg")
# show image with watermark in preview
Photo by Kuma Kum on Unsplash

So there you go!

You can use the Pillow Library for a lot more. The above are just a few basic samples, which i frequently used and consider especially useful. Try it out yourself, the full code snippets and more… can be found by clicking right here.



Analytics Vidhya

Software engineer, runner, hiker, fitness enthusiast.


See more recommendations