Python is now one of the most widely used programming languages in the world. It can be used to perform various functions and tasks using a simple syntax.
One important function Python can perform is automatic processing of digital images, which can be done using Pillow.
In this tutorial, we’ll show you how to process images using the Pillow module. Then, we’ll take it a step further and demonstrate how to implement some basic image operations.
To follow along with this tutorial, you should have basic knowledge of Python and the Python 3 interpreter installed on your local machine.
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
Pillow is a fork of the Python Imaging Library (PIL). It is a free and open-source library for manipulating and processing images.
PIL is a powerful library in its own right, but it hasn’t been updated since 2009 and doesn’t support Python 3. Pillow provides more features and support for Python 3.
Pillow supports a range of image file formats, such as .PNG, .JPEG, .PPM, .GIF, .TIFF, and .BMP. You can perform various operations on images such as cropping, resizing, adding text, rotating, grayscaling, and so much more using this library.
You can install Pillow using pip, a package manager for Python packages:
python3 -m pip install --upgrade pip python3 -m pip install --upgrade Pillow
Pillow offers the Image object, which has inbuilt functions and properties on which manipulation operations can be carried out.
To get started, first import the I``mage object to the Python file.
from PIL import Image
Next, load the image by calling the Image.open() function, which returns a value of the Image object data type.
image = Image.open('sample.jpg')
For our examples, we’ll use a sample image from Unsplash.
Also worth noting, the images are in the same directory as the Python script file being run.
Image objectThere are several properties of the image we can access to get more data from the image:
image.width returns the width of the imageimage.height returns the height of the imageimage.format returns the file format of the image (e.g., .JPEG, .BMP, .PNG, etc.)image.size returns the tuple height and weight of the imageimage.palette returns the color palette table, if one existsimage.mode returns the pixel format of the image (e.g., 1, L, RGB, CMYK)We are also able to process and manipulate our images using various operations.
Any changes made to the Image object can be saved to an image file with the save() method. All the rotations, resizing, cropping, drawing, and other image manipulations are done through via calls on this Image object.
Let’s zoom in and explore some of these operations in more detail.
Pillow supports a wide variety of images formats. An image can be converted from one format to another as follows:
image = Image.open('sample.jpg')
image.save('sample_formatted.png')
First, the image is loaded. Then, Pillow sees the file extension specified as PNG, so it converts the image to .PNG before saving it to file.
You can resize images by creating a thumbnail of the image using Pillow.
Using the thumbnail() function, the image is resized to keep its aspect ratio. This takes two values representing the maximum width and maximum height of the thumbnail.
image = Image.open('sample.jpg')
image.thumbnail((200, 200))
image.save('sample_thumbnail.jpg')
![]()
The image is then resized within the maximum limit so as not to be overstretched or blurred.
If you need the image to face a different direction, Pillow enables you to flip it. This is done using the transpose function, which takes any of the following parameters:
Image.FLIP_LEFT_RIGHT, which flips the image horizontallyImage.FLIP_TOP_BOTTOM, which flips the image verticallyImage.ROTATE_90, which rotates the image to a certain degree, depending on the angleimage = Image.open('sample.jpg')
image.transpose(Image.FLIP_TOP_BOTTOM)
image.save('sample_flip.jpg')

The resulting image is flipped vertically.
Alternatively, you can rotate images using the rotate() method. This takes an integer or float argument representing the degrees of rotation and returns a new Image object of the rotated image. The rotation is counterclockwise.
image = Image.open('sample.jpg')
image.rotate(90)
image.save('image_rotate90.jpg')

The image is rotated by an angle of 90 degrees.
To crop an image is to cut out only a specific portion. Cropping often comes into play when editing images for web applications.
The crop() function in Pillow requires the portion to be cropped as a rectangle. The method takes a box tuple that defines the position and size of the cropped region and returns an Image object representing the cropped image. The region is defined by a 4-tuple, where coordinates are (left, upper, right, lower).
image = Image.open('sample.jpg')
image.crop(200, 50, 450, 300)
image.save('sample_cropped.jpg')

In the example above, the first two values represent the starting position from the upper-left; the third and fourth values represent the distance in pixels from the starting position toward the right and bottom direction.
The full size of the cropped image can be calculated as 250×250 pixels.
There are various forms of pixel representations, including L (luminance), RGB, and CMYK.
Pillow allows you to convert images between different pixel representations using the convert() method. The library supports transformations between each supported mode as well as the “L” and “RGB” modes. To convert between other modes, you may have to use an “RGB” image.
image = Image.open('sample.jpg')
grayscale_image = image.convert('L')
grayscale_image.save('sample_grayscale.jpg')

Using the convert function, the sample image is converted from RGB to L (luminance) mode, which will result in a grayscale image.
The act of modifying and enhancing images to improve the appearance can be known as filtering.
Using the ImageFilter module from Pillow, you can access to the filter() method and use various filter techniques, including:
BLURCONTOURDETAILEDGE_ENHANCEEDGE_ENHANCE_MOREEMBOSSFIND_EDGESSHARPENSMOOTHSMOOTH_MOREFor example, let’s take a look at the FIND_EDGES filter:
from PIL import Image, ImageFilter
image = Image.open('sample.jpg')
edges_image = image.filter(ImageFilter.FIND_EDGES)
edges_image.save('sample_edges.jpg')

The filter processes the image to display the edges of the image.
Any image can be processed using any of the filters available to produce the desired output.
Now that we have a basic understanding of the library, let’s create a simple python script to automate the processing of various types of images.
Let’s say you’re given a group of images and asked to add a watermark to each image.
To solve the problem, you can create a Python file called script.py in the same folder as the images.
First, import all necessary modules:
import os from PIL import Image
The OS module in Python provides functions for creating and removing a directory and changing and identifying the current directory.
Create a directory for the processed image:
os.makedirs('watermarked_images')
Store the width and height of the logo image:
logo_image = Image.open('watermark_logo.png')
logo_image = logo_image.resize((50, 50))
logo_width, logo_height = logo_image.size
Use the os.listdir function together with a for loop:
for image in os.listdir('./images'):
try:
# Separting the filepath from the image's name
path, filename = os.path.split(image)
filename = os.path.splitext(filename)[0]
Open the image:
image = Image.open('./images/'+image)
#Resizing the image to a set size.
edited_image = image.resize((300, 300))
#Setting the position for the placement
width = edited_image.width
height = edited_image.height
Use the paste function to position the logo on the image:
edited_image.paste(logo_image, (width - logo_width, height - logo_height), logo_image)
Save the images in the new directory:
edited_image.save('./watermarked_Images/' + filename + ".jpg")
Each image in the directory has been processed and the watermark added. This script enabled us to efficiently perform the task in less time.
You can also check out the GitHub repository for the full code and resources associated with this tutorial.
Pillow is a powerful library for processing images in Python. In this tutorial, we established a foundational understanding of how to perform basic operations on images in Python using Pillow.
If you want to learn more, check out the official Pillow documentation.
Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
server-side
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the November 5th issue.

A senior developer discusses how developer elitism breeds contempt and over-reliance on AI, and how you can avoid it in your own workplace.

Examine AgentKit, Open AI’s new tool for building agents. Conduct a side-by-side comparison with n8n by building AI agents with each tool.

AI agents powered by MCP are redefining interfaces, shifting from clicks to intelligent, context-aware conversations.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now