Cropping Images with Pillow
Learn how to crop rectangular regions from images with Python and Pillow using image coordinates, crop boxes, previewing, saving, and troubleshooting.
Image cropping means creating a new image from a selected rectangular portion of an existing image. Cropping is useful for isolating a subject, removing unwanted borders, preparing thumbnail sources, or extracting a small detail from a photograph.
Prerequisites and Pillow Installation
You should be comfortable running a basic Python script, importing modules, assigning variables, calling functions, working with tuples, and using image filenames or file paths.
Pillow is a Python imaging library. It is commonly imported through the PIL package namespace. If it is not installed in the Python environment used by your script, run:
python -m pip install Pillow
Opening an Image in Pillow
Import Image from PIL, then use Image.open() to load the source file. The returned Image object represents the original image and can be used to create a separate cropped result.
from PIL import Image
img = Image.open("handsome.jpg")
The variable img refers to the original image. Cropping does not require you to replace that variable; you can store the result in another variable.
Understanding Pillow Image Coordinates
Image coordinates use a screen-oriented system rather than the usual mathematical graph system. The origin, coordinate (0, 0), is at the upper-left corner of the image.
- x increases as you move to the right.
- y increases as you move downward.
- Moving left decreases x.
- Moving upward decreases y.
On a typical graph, y increases upward. In an image, y increases downward because rows are counted from the top of the image.
| Movement | Coordinate change |
|---|---|
| Move right | x increases |
| Move left | x decreases |
| Move down | y increases |
| Move up | y decreases |
The Crop Box Format
The crop() method requires a four-value crop box. A crop box is a tuple of numeric pixel coordinates written in this order:
(left, upper, right, lower)
left and upper identify the rectangle's top-left boundary. right and lower identify its bottom-right boundary. Pixel coordinates are locations measured in pixels within the image.
| Tuple position | Name | Meaning | Axis |
|---|---|---|---|
| 1 | left | Left crop boundary | x |
| 2 | upper | Top crop boundary | y |
| 3 | right | Right crop boundary | x |
| 4 | lower | Bottom crop boundary | y |
Using Image.crop()
Call crop() on an Image object and store the returned Image object in a new variable. The operation extracts the rectangular region; it does not require replacing the original image variable.
from PIL import Image
img = Image.open("handsome.jpg")
area = (555, 344, 598, 380)
cropped_img = img.crop(area)
cropped_img.show()
In this example, cropped_img contains the region from x=555 through x=598 and y=344 through y=380. The crop has a width of 598 - 555 = 43 pixels and a height of 380 - 344 = 36 pixels.
show() opens the result for temporary previewing. To write the cropped image to disk, call save():
cropped_img.save("cropped-detail.jpg")
Use an output filename and an appropriate image extension. Previewing with show() alone does not create a saved output file.
Example: Extract a Small Photograph Detail
Suppose a larger photograph contains a narrow detail whose top-left corner is at (555, 344) and whose opposite corner is at (598, 380). Use those measurements directly in the required edge order.
from PIL import Image
source = Image.open("handsome.jpg")
crop_box = (555, 344, 598, 380)
detail = source.crop(crop_box)
detail.show()
detail.save("cropped-detail.jpg")
The expected result is a new 43 by 36 pixel image containing only the selected region.
Example: Crop a Header Region
To take the upper 200 pixels of an image that is at least 800 pixels wide, use the full-width rectangle from the upper-left corner to coordinate (800, 200):
from PIL import Image
source = Image.open("header-source.jpg")
header = source.crop((0, 0, 800, 200))
header.save("header-crop.jpg")
This crop spans 800 pixels in width and the first 200 pixels in height.
Finding Crop Coordinates
- Open the source image in an image editor, image viewer, or graphics program that displays the pointer position in pixels.
- Move to the intended top-left corner and record its coordinate as
(x, y). - Move to the intended bottom-right corner and record that coordinate.
- Transfer the values into the Pillow order:
(left, upper, right, lower). - Zoom in when selecting a small region so both boundaries can be measured more precisely.
For example, if the editor reports (555, 344) at the first corner and (598, 380) at the opposite corner, the Pillow crop tuple is (555, 344, 598, 380).
Verifying the Crop Result
After creating the crop, confirm that the output contains the intended visual region. Check its dimensions using the boundary differences:
- Crop width =
right - left - Crop height =
lower - upper
If the selection is shifted, too large, too small, or missing part of the target, revise one or more boundaries. Reopen the source, zoom in, remeasure both corners, and run the crop again.
Troubleshooting
The crop is in the wrong location
The coordinate origin or axis direction may have been interpreted incorrectly. Remember that (0, 0) is at the upper-left, x increases to the right, and y increases downward.
The selected region is too large or too small
One or more boundaries were probably measured inaccurately. Zoom into the source image and remeasure the top-left and bottom-right corners.
The crop box values seem to be in the wrong order
Convert the measured points to edge order. Pillow expects (left, upper, right, lower), not an arbitrary sequence of x/y values.
Python cannot import PIL
Pillow may be missing from the active Python environment. Install it with python -m pip install Pillow, then ensure that your script runs with the same Python interpreter.
The result is not written to disk
show() is for viewing a temporary result. Add cropped_img.save("output.jpg") or another suitable output filename to save the crop.
Complete Cropping Pattern
from PIL import Image
source = Image.open("input.jpg")
crop_box = (left, upper, right, lower)
cropped = source.crop(crop_box)
cropped.show()
cropped.save("output.jpg")
Replace the placeholder boundary names with numeric pixel coordinates measured from the source image. For related Pillow operations, see Pillow image attributes, rotating an image, and creating watermarks.