Skip to content

How to crop images with Python (PIL): The Ultimate Guide

Python triangular crop

Cropping is probably one of the most commonly used image editing tasks in both mobile apps and image editing software for desktops.

In this tutorial we will demonstrate how to crop images using Python’s PIL library. Image cropping is sometimes used synonymously with image clipping or image trimming as well as image cutting.

Let’s dive in and start checking out a few examples…

What is image cropping?

Cropping is a verb with a very old agricultural root word cropp. Cropp meant the top of a herb in Old English (kropf in Old High German) and the meaning of cropping as a verb evolved as humankind became more civilized and industrialized to mean “to cut off the tip of something” (such as cropping fabric in fashion, cropping produce in agriculture or cropping hair in personal care etc.).

Similarly, cropping means to cut off, trim or extract a piece of image in image editing context. With the surge of digital photography and mobile phones this term became extremely popular and its the main feature in almost every photo editing software or app.


We will cover the basic computational image cropping methods in this Python tutorial as well as other more advanced programmatic cropping techniques that can trim images in various geometric shapes and even based on text.

What can I do with cropping?

Image cropping is a major image editing operation and it can be useful for a variety of purposes.

  • Cropping in general (usually rectangular) can be useful to:
    • leave out certain parts of the image
    • reduce the size of an image
    •  trim the sides/frames of images
  • Cropping in circular or other geometric shapes can be useful to:
    • create profile pictures
    • generate new image items to paste on another image
    • generate creative promotional material
    • supplement/decorate pitch decks, white papers, reports etc.
  • Additionally, cropping images in text shapes allows:
    • generating creative banners,
    • slogans,
    • titles
    • inspirational quotes,
    • social media posts,
    • consulting proposals
    • and similar material with very aesthetic decorative elements.

We will demonstrate all of these cropping methods with Python below and build from the most simplistic to more complex cropping implementations.

Holy Python is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Image.crop method

Crop method is quite simple using Python’s PIL library. Let’s first import the modules we are going to use.

We will only need the Image module but we might need ImageDraw and ImageFont later for more advanced image cropping implementations.

from PIL import Image, ImageDraw, ImageFont
Application of the .crop method of PIL’s Image module is the most straightforward way to crop images.
.crop method has one mandatory argument which is the coordinates for cropping.
.crop method is applied on an image object and it returns a cropped image object based on the box coordinates provided as below.
Let’s start with opening an image first.
img ='pup_running_original.jpg')

And then we can crop this image as below and we can assign the returned image which will be cropped to a variable named cropped.img.

Here are the results of both images upon using the .show() method after our Python codes.

Original Image

Bichon Frise running in the park.

I think it’s a Bichon Frise but I’m not sure.

Photo cred: Caleb Fisher @Unsplash.

Cropped Image

Buchon Frise running (cropped version)

After adding the Python code below to our initial code we get the image above.

cropped_img=img.crop((50,280, 450,650))

Trimming the Sides

Using the crop method more methodically, we can trim an equal margin value from each side of the image. This approach can be useful to fit an image to predefined dimensions without lowering the image quality.
Also sometimes, images can have empty surroundings or unwanted items around them such as text or frames.
We prepared two examples to demonstrate exactly those cases. First one is an image with text elements and frames around it.  Let’s say you you run the social media accounts of a global enterprise and all of a sudden you needed 1000 images with frames de-framed.
Obviously this task would require exceptional amount of time and patience and result in the loss of  thousands of dollars worth intellectual resources for the company. GUI programs aren’t optimized for scaled image editing and they are bloated with hundreds of unnecessary features and graphic components which make them very sluggish and unreliable at times.

Case 1: Removing Frames from an Image

Python Image with Text and Frame
img ='/home/holypython/quote_with_frame.png')

x,y = img.size

Python Image with Text and Frame

Case 2: Removing Text from an Image

Our second example is based on an image with some text at the bottom. Let’s say this textual information became obsolete and needs to be removed from the image. Luckily it’s at the bottom edge of the image and cropping a bit from the bottom won’t hurt anything. We can easily implement the following Python code to achieve our image editing objective.

Like the previous example this Python code can be applied in a for loop or a while loop to scale the same implementation and achieve batch cropping results.

Below, we have a lovely photo of a yellow van on a desert road. Oftentimes old digital cameras had automatic settings to add date as textual information printed right on the image. A bit of a disruptive practice from the early days of digital photography.

Check out the image below. We will conveniently crop this text using Python’s PIL library.

Python Image with disruptive text at the bottom

Our code uses the .crop method which again requires box coordinates (x0, y0, x1, y1). This time, we are starting from the very top left of the image (x0=0 & y0=0) and the box goes all the way to the right (x1=full width) while the box leaves a small margin from the bottom (y1=full height minus 60 pixels). Et voila!

img ='/home/holypython/van_desert_road.png')

x,y = img.size

Python Image with disruptive text cropped

If you had 10.000 images to edit, the 4 line Python code above could be a lifesaver. Similar situation can arise from space imagery (due to hardware or organization implementations) as well as medical imaging in the healthcare industry.

Below, you can see our Python tutorial’s section regarding batch cropping applications.

Batch Cropping Images with Python

Everything we have demonstrated above can also be applied to batch processing of images. Probably the most convenient way of applying image processing to multiple images with Python is by placing them in a folder and then taking advantage of python’s os library to read each image’s name and open them for editing.
Take a look.
import os
for i in os.listdir():

Once we can effortlessly get all the file names we can easily use “Python for loops or while loops” to iterate our image cropping Python scripts on them.

import os
for i in os.listdir():
    img =
    x,y = img.size
    new_img = img.crop(0,100,x,y)[:-3]+"_cropped.png")
i[:-3] slices the strings which consist of image names in a way that they are stripped from the .jpg extensions. Then we add “_cropped.png” suffix to each new image’s name.
You can visit this Python lesson regarding how to slice Python strings.

Cropping Images in Geometric Shapes with Python

If you have been trying to crop images in circular or other geometrical shapes to no avail, you are in luck. We will demonstrate how to do exactly that in this session.

We will also stick to the PIL (pillow) image editing library 100%. Although similar results can be achieved using the opencv library, it is not as intuitive or user-friendly for this purpose. Even just opening and closing a window to show the images can be a hassle in opencv.

from PIL import Image, ImageDraw, ImageFilter, ImageFont
img ='rishi-ragunathan-fs6NPHYMN7o-unsplash.jpg').convert("RGBA")

background ="RGBA", img.size, (0,0,0,0))
mask ="RGBA", img.size, 0)
draw = ImageDraw.Draw(mask)
#draw.regular_polygon((300,300,300), 3, rotation=360, fill='green', outline=None)
draw.ellipse((300,50,650,400), fill='green', outline=None)
new_img = Image.composite(img, background, mask)

Let’s talk about the technique we are going to apply to achieve geometric cropping for a sec. We will use Image module’s .composite method for our purpose.

Image.composite method is used for merging images or pasting an image on top of another.

We also know that RGBA images have an alpha channel in addition to RGB (red-green-blue) color channels and alpha channel can be used to manage the transparency levels of the image. You can read about image modes with Python for more fundamental computational photography knowledge.

So then, we can create a fully transparent new image (alpha turned down to 0, RGB doesn’t matter so anything between 0-255.) and then paste our image on top of this transparent canvas. While pasting the new image, we can also use the mask argument which will ensure pasting is done based on the shape of that mask.

Here is how it looks in theory:

new_img = Image.composite(img, background, mask)

background, new_image and mask are all image objects which we are using for different purposes.

  • img: Actual image that’s being cropped
  • background: 100% transparent background layer
  • mask: The shape in which image will be cropped, used as mask layer

Circular Cropping

For circular cropping we need to create a mask in circle shape. We can do this by drawing a circle on a transparent layer and fill it with any color.

Circle is a special type of ellipse where all points are in equal distance from the center and we can draw a circle using the .ellipse method from the ImageDraw module. The only trick is the box needed to draw the circle needs to be a square. This can be achieved by following.

x1-x0 = y1-y0 when applying the ellipse drawing in this method: ImageDraw.ellipse((x0, y0, x1, y1))

Below you can find the Python code that crops a portrait in circular shape in 5 steps.

  1. We will open the image to be cropped (img)
  2. We will create a transparent background (background)
  3. We will create a transparent mask layer (mask)
  4. We will draw a circle on the mask layer (mask)
  5. We will paste the img on background based on the mask.
from PIL import Image, ImageDraw, ImageFilter, ImageFont
img ='man_portrait.jpg').convert("RGBA")
background ="RGBA", img.size, (0,0,0,0))

mask ="RGBA", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((20,190,630,800), fill='green', outline=None)

new_img = Image.composite(img, background, mask)

Here the box has equal sides horizontally and vertically to create a circular mask.

630-20 = 610
800 – 190 = 610

Original Image
Full size man portrait image
Circular Cropping Output
Image after circular cropping with PIL's Image.composite

Elliptical Cropping

from PIL import Image, ImageDraw, ImageFilter, ImageFont
img ='woman_portrait.jpg').convert("RGBA")
background ="RGBA", img.size, (0,0,0,0))

mask ="RGBA", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((70,70,470,540), fill='green', outline=None)

new_img = Image.composite(img, background, mask)
Original Image
Full size woman portrait
Elliptical Cropping Output
Image after elliptic cropping with PIL's Image.composite

You can also use this tutorial about automated face recognition with Python and merge it with Batch Cropping techniques explained in this tutorial to apply circular face cropping to thousands or even millions of images.

Triangular Cropping

Once you understand the strategy explained in the circular cropping, you can imagine the same technique conveniently can be applied to any geometrical or even arbitrary shape.
For example to create a triangular cropping we can repeat the same exact process above but draw a triangle on the mask layer instead of a circle or ellipse.
To do that we can use the .regular.polygon method from ImageDraw module and pass 3 sides to its n_sides arguments. And the first argument is the circle that will be used to fit the triangle in which takes 3 arguments (x, y, radius)

ImageDraw.regular_polygon(bounding_circle, n_sides, rotation=0, fill=None, outline=None)

from PIL import Image, ImageDraw, ImageFilter, ImageFont
img ='/home/usa/Downloads/Wallpaperz/nick-perez-duvq92-VCZ4-unsplash.jpg').convert("RGBA")

background ="RGBA", img.size, (0,0,0,0))

mask ="RGBA", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.regular_polygon((300,300,300), 3, rotation=360, fill='green', outline=None)

new_img = Image.composite(img, background, mask)

base_img ="RGBA", (4000, 4000))
base_img.paste(new_img, (300,300), new_img)

Here the bounding circle starts at point (300,300) and has a radius of 300 as well. Triangle is fit inside this circle. Then we use this triangle drawing as a mask to past our image in triangular shape using the .composite method.

Python Image with triangular cropping

Using the same methods you can even crop images in arc shapes or pieslices which is a circular shape with a degree meaning you can create semi-circles or any incomplete circle shape based on the degree (360 degrees would yield a full circle).

Here are a couple of more examples for triangular cropping with Python’s PIL image editing library.

Python Image with triangular cropping: NYC
Python Image with triangular cropping: Field

Pentagonal Cropping

We can apply polygon drawing to create a pentagonal (5 sided) shape and create a pentagonal cropping with Python based on that drawing similar to the examples above.

The Python code’s drawing section for that will include the following snippet.

draw.regular_polygon((1500,1000,1300), 5, rotation=360, fill='green', outline=None)
First two parameters are the most important in this cropping task:
  • Bounding_circle: This is a tuple with 3 elements (x,y,radius). X,y are the coordination to start the crop from and the radius is the radius of the circle in which pentagon will be drawn. We’re using (1500,1000,1300) for a 1300 pixel radius circling the pentagon and starting points of (1500,1000)
  • n_sides: This is the parameter for sides of the polygon. For Pentagon we are entering 5.
Python Image with pentagonal cropping

Hexagonal Cropping

Hexagon is a polygon shape similar to a pentagon except it has 6 sides instead of 5.

Following the same methods here we are drawing a hexagon and then using it as mask layer to create an impressive hexagonally cropped Python image.

draw.regular_polygon((3600,1800,2300), 6, rotation=360, fill='green', outline=None)

Regular polygon method (ImageDraw.regular_polygon) takes a tuple (bounding_circle) as first argument which consists of x,y coordinates and the radius of the polygon’s outer circle. (x,y,r). 6 is passed to n_sides argument for hexagon which is the second one and the rest is rotation, fill and outline colors.

Python Image with hexagonal cropping

Rounded Rectangle Cropping

To take advantage of rounded rectangle cropping, all you need to do is draw a rounded rectangle as mask layer instead. Below we are drawing a rectangle with rounded corners at 60 degree radius. You can apply the Python code above with the shape in the Python code below to achieve a result as in the image.

draw.rounded_rectangle((20,190,630,800), 60, fill='green', outline=None)
Python Image with rounded rectangle cropping

Cropping Images in Text Shapes

Once you understand the logic of cropping images based on mask layers with Python, you can come up with very creative applications. For example text objects can also be drawn on Python images using the PIL image editing library.

So, we can use the ImageFont and ImageDraw modules to draw text objects and use it as the mask layer to crop images based on these text objects.

Results will be very aesthetic and computationally feasible meaning a lot more convenient than resource-hungry GUI photo editing applications. You can use it to create amazing titles, slogans, inspirational quotes, pitch deck headers, blog headers magazine covers etc. etc with filling as any of your favorite images.

Here are some examples.

from PIL import Image, ImageDraw, ImageFilter, ImageFont
img ='/home/usa/Downloads/Wallpaperz/nick-perez-duvq92-VCZ4-unsplash.jpg').convert("RGBA")

background ="RGBA", img.size, (0,0,0,0))
mask ="RGBA", img.size, 0)
draw = ImageDraw.Draw(mask)

font = ImageFont.truetype('Inconsolata-Bold.ttf', 550)
draw.text((50,1100), "HOLYPYTHON", fill='blue', font=font)

new_img = Image.composite(img, background, mask)

Here is Holypython text cropped from an artistic drawing.

Python Image with rounded rectangle cropping

* Please note that following examples follow the same logic with the cropping Python code above. I’m only including the draw text parts to avoid repetition and cluttering the screen. Just replace the relevant lines from the Python example above to reach the same results.

font = ImageFont.truetype('Inconsolata-Bold.ttf', 750)
draw.text((50,1100), "HOLYPYTHON", fill='blue', font=font)
This one is uber-cool. Holypython written in lego texture. This text crop gives a physical 3D feeling as if the text was written with physical lego objects.
Python Image with rounded rectangle cropping

This one is more like a skincare product slogan or maybe a header from a biomedical startup’s pitch deck. You can almost feel the vitality of the leaves. Considering how easy it is to crop such visuals with Python it’s a hugely successful experiment already.

font = ImageFont.truetype('Inconsolata-Bold.ttf', 750)
draw.text((50,1100), "REVITALIZE", fill='blue', font=font)
Python Image with rounded rectangle cropping

This one is written with Inconsolata-Black.ttf font. You can list your system’s fonts using fc-list in Linux. (Or this might be more useful: fc-list | grep .ttf)

(In this example piped with the results of the fc-list command, grep is an ultra useful Linux command. You can check out this tutorial about using grep recursively to search contents of files in your operating system.)

In Windows and Mac you can open Font GUI applications of the operating systems to explore the fonts installed in your system. You can always install new fonts using Google Font free font repository as well.

font = ImageFont.truetype('Inconsolata-Black.ttf', 750)
draw.text((50,1100), "REDEFINE", fill='blue', font=font)
Python Image with rounded rectangle cropping
font = ImageFont.truetype('Inconsolata-Black.ttf', 1250)
draw.text((50,1100), "BREEZE", fill='blue', font=font)
Python Image with rounded rectangle cropping


In this Python Tutorial we extensively covered different techniques to crop images using Python and its image editing PIL (pillow) library.

We took advantage of different modules from PIL such as Image, ImageDraw and ImageFont and we used several methods applied on Python PIL image objects. These methods are:

  • .composite,
  • .crop
  • .draw,
  • .text,
  • .polygon,
  • .rounded_rectangle,
  • .ellipse,
  • .open
  • .show

You can, of course, save these generated image objects with the .save method  instead of just showing them with the .show method. You can refer to this quick tutorial how to save Python images.

We hope this computational photography tutorial was useful for our audience. Computational photography and digital image editing can be incredibly beneficial for organizations of all sizes and startups and they open many doors to impressive creativity.