Pillow online course

Rotate and Flip Images with Pillow

Learn to rotate images by arbitrary angles or 90-degree increments and flip them horizontally or vertically with Python Pillow.

Pillow is a Python imaging library that provides the PIL package interface. In this lesson, you will rotate images by arbitrary angles, rotate them by exact right angles, flip them, preview results, and save the transformed images.

This lesson assumes basic Python imports, variables, method calls, file paths, and package installation. Install Pillow if it is not already available:

python -m pip install Pillow

Open an image with Pillow

Import Image from PIL, then call Image.open() with the input file path. The returned object represents the image in memory.

from PIL import Image

image = Image.open("input.jpg")

Methods such as rotate() and transpose() generally return a new Image object. They do not immediately replace or modify the original image file on disk. You must call save() on the returned object to create an output file.

For related information about properties such as dimensions and mode, see Image Attributes.

Rotate an image by an arbitrary angle

Use Image.Image.rotate() when the angle is not limited to a right angle. The angle argument is measured in degrees. By default, positive angles rotate counter-clockwise.

from PIL import Image

image = Image.open("input.jpg")
rotated = image.rotate(45)
rotated.show()

The assignment is important: rotated refers to the new image, while image still refers to the original object. show() opens the result using a local image viewer and is mainly useful for quick inspection during development. It is not the normal way to publish or preserve a result; use save() for that.

Canvas size and clipped corners

A rotation such as 45 degrees can make the rectangular image extend beyond its original canvas. With the default behavior, the output generally keeps the source dimensions, so parts of the rotated content can be clipped. Newly exposed corner areas can also contain a background color.

Pass expand=True when the complete rotated image must fit inside the result. Pillow then enlarges the output canvas as needed.

from PIL import Image

image = Image.open("input.jpg")
rotated = image.rotate(
    45,
    expand=True,
    resample=Image.Resampling.BICUBIC,
    fillcolor="white"
)
rotated.save("rotated.png")

fillcolor selects the color for pixels exposed by the rotation. The value must be compatible with the image mode. For example, an RGB image can use a color such as "white" or (255, 255, 255), while an RGBA image can use a four-component tuple containing red, green, blue, and alpha values.

OptionPurposeTypical valueWhen to use it
angleSets the rotation amount in degrees.45Use any angle for arbitrary-angle rotation.
expandChanges the output canvas size to contain the rotated image.TrueUse it to prevent clipping at non-right angles.
fillcolorSets the color of newly exposed background pixels."white"Use it when the default background is unsuitable.
resampleChooses the interpolation method used to calculate transformed pixels.Image.Resampling.BICUBICUse it to balance quality and speed for arbitrary angles.

Choose a resampling method

resample is the interpolation method Pillow uses to calculate pixels during transformations. Faster methods can be adequate for quick previews, while higher-quality methods usually produce smoother results but require more processing.

Image.Resampling.BICUBIC is often a suitable choice for photographic images:

rotated = image.rotate(
    22.5,
    expand=True,
    resample=Image.Resampling.BICUBIC
)

Interpolation has little or no practical effect for exact 90-degree steps. For those operations, use transpose() instead.

Rotate images in 90-degree increments

transpose() performs fixed geometric transformations, including exact 90-degree rotations. These operations do not require interpolation and are especially suitable for right-angle changes.

from PIL import Image

image = Image.open("input.jpg")
rotated = image.transpose(Image.Transpose.ROTATE_90)
rotated.save("rotated_90.jpg")

The current Pillow enum values represent these orientations:

  • Image.Transpose.ROTATE_90: rotates the image 90 degrees.
  • Image.Transpose.ROTATE_180: rotates the image 180 degrees.
  • Image.Transpose.ROTATE_270: rotates the image 270 degrees.
TaskRecommended methodOperation or argumentResult
Arbitrary-angle rotationrotate()image.rotate(angle)Rotates by the requested number of degrees.
90-degree rotationtranspose()Image.Transpose.ROTATE_90Rotates 90 degrees.
180-degree rotationtranspose()Image.Transpose.ROTATE_180Turns the image upside down.
270-degree rotationtranspose()Image.Transpose.ROTATE_270Rotates 270 degrees, equivalent to 90 degrees clockwise.
Horizontal fliptranspose()Image.Transpose.FLIP_LEFT_RIGHTMirrors the image from left to right.
Vertical fliptranspose()Image.Transpose.FLIP_TOP_BOTTOMInverts the image from top to bottom.

Flip an image horizontally or vertically

A horizontal flip creates a mirror image across the vertical axis. Left and right exchange places, but the top remains the top.

from PIL import Image

image = Image.open("input.jpg")
flipped = image.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
flipped.save("flipped_horizontal.jpg")

A vertical flip creates an upside-down version across the horizontal axis. The top and bottom exchange places, while left and right remain in their corresponding sides.

from PIL import Image

image = Image.open("input.jpg")
flipped = image.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
flipped.save("flipped_vertical.jpg")

Both flip operations return a new image object. The original image object and its source file are not replaced automatically.

Preserve transparency after rotation

Images with transparency commonly use the RGBA image mode. Its pixels contain red, green, blue, and alpha components; an alpha value of zero is fully transparent.

When rotating a transparent PNG, use an RGBA-compatible transparent fill and save the result as PNG:

from PIL import Image

image = Image.open("transparent.png").convert("RGBA")
rotated = image.rotate(
    45,
    expand=True,
    fillcolor=(0, 0, 0, 0)
)
rotated.save("transparent_rotated.png")

Saving transparent output as JPEG can remove the alpha channel because JPEG does not support transparency. Choose PNG when the transparent areas must remain transparent. The image mode, such as RGB, RGBA, or L, affects which fill colors are valid.

Save transformed images safely

Call save() on the transformed image and use an output filename whose extension identifies the intended format.

rotated = image.rotate(45, expand=True)
rotated.save("photos/portrait_rotated.png")

Use a different output path from the input path unless intentionally replacing the source. Naming files with the transformation and format, such as rotated_90.jpg or flipped_horizontal.png, makes the result easier to identify.

Pillow API compatibility

Modern Pillow code should use enum values under Image.Transpose, such as Image.Transpose.ROTATE_90 and Image.Transpose.FLIP_LEFT_RIGHT.

Older examples may use names such as Image.ROTATE_90 or Image.FLIP_LEFT_RIGHT. Recognizing those names helps when reading existing code, but prefer the modern syntax in new programs and documentation.

Troubleshooting

  • Parts disappear: A non-right-angle rotation probably used the original-sized canvas. Pass expand=True.
  • Corners are black or opaque: Supply an appropriate fillcolor. For transparent PNG output, use RGBA mode and fillcolor=(0, 0, 0, 0).
  • The result is jagged or blurry: Arbitrary-angle rotation requires interpolation. Try Image.Resampling.BICUBIC and inspect the result at its target size.
  • Old constants cause warnings or errors: Replace older names with values from Image.Transpose.
  • Transparency is lost: Confirm that the image supports alpha and save it as PNG rather than JPEG.
  • No output file exists: Rotation and flipping create an in-memory image. Call save() on the returned object with an explicit path.

Key points

For more Pillow image workflows, continue with Cropping Images, review RGB Channels, or explore the Pillow Online Course.