Pillow online course

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.

MovementCoordinate change
Move rightx increases
Move leftx decreases
Move downy increases
Move upy 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 positionNameMeaningAxis
1leftLeft crop boundaryx
2upperTop crop boundaryy
3rightRight crop boundaryx
4lowerBottom crop boundaryy

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

  1. Open the source image in an image editor, image viewer, or graphics program that displays the pointer position in pixels.
  2. Move to the intended top-left corner and record its coordinate as (x, y).
  3. Move to the intended bottom-right corner and record that coordinate.
  4. Transfer the values into the Pillow order: (left, upper, right, lower).
  5. 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.