How to resize an image in Python

Learn how to resize images in Python. Explore different methods, tips, real-world applications, and how to debug common errors.

How to resize an image in Python
Published on: 
Tue
Mar 3, 2026
Updated on: 
Wed
Apr 1, 2026
The Replit Team

To resize an image in Python is a common task for web development and data augmentation. Python libraries offer simple tools to complete this process with just a few lines of code.

In this article, we'll explore several techniques and the libraries that enable them. You'll get practical tips for efficient implementation, see real-world applications, and receive clear advice to help you debug common issues.

Basic image resizing with PIL.Image.resize()

from PIL import Image
img = Image.open('sample.jpg')
print(f"Original size: {img.size}")
resized_img = img.resize((300, 200))
print(f"Resized to: {resized_img.size}")
resized_img.save('resized_sample.jpg')--OUTPUT--Original size: (1024, 768)
Resized to: (300, 200)

The code uses the Pillow library, a powerful tool for image processing in Python. The key function here is resize(), which is called on an Image object. It accepts a tuple defining the new dimensions in (width, height) format.

Crucially, resize() doesn't alter the original image. Instead, it returns a new, resized Image object. You must then explicitly save this new object to a file using the save() method to see the result on your disk.

Popular libraries for image resizing

While Pillow is a popular choice, other libraries like OpenCV, scikit-image, and even Matplotlib offer their own robust alternatives for resizing images in Python.

Resizing images with cv2.resize()

import cv2
img = cv2.imread('sample.jpg')
print(f"Original size: {img.shape[1]}x{img.shape[0]}")
resized_img = cv2.resize(img, (300, 200))
print(f"Resized to: {resized_img.shape[1]}x{resized_img.shape[0]}")
cv2.imwrite('resized_sample.jpg', resized_img)--OUTPUT--Original size: 1024x768
Resized to: 300x200

OpenCV, a library geared toward computer vision, treats images as NumPy arrays. The process is straightforward: you load an image with cv2.imread(), resize it with cv2.resize(), and save the result using cv2.imwrite().

  • The main difference from Pillow is how you get the dimensions. OpenCV uses the shape attribute, where the height is img.shape[0] and the width is img.shape[1].
  • The cv2.resize() function itself is similar, accepting the image and a new (width, height) tuple.

Using scikit-image for image resizing

from skimage import io, transform
img = io.imread('sample.jpg')
print(f"Original size: {img.shape[1]}x{img.shape[0]}")
resized_img = transform.resize(img, (200, 300))
print(f"Resized to: {resized_img.shape[1]}x{resized_img.shape[0]}")
io.imsave('resized_sample.jpg', resized_img)--OUTPUT--Original size: 1024x768
Resized to: 300x200

Scikit-image, part of the SciPy ecosystem, offers a scientific approach to image processing. You'll use the io module for loading and saving images with imread() and imsave(), while the transform.resize() function handles the actual resizing.

  • Pay close attention to the dimensions. The transform.resize() function expects the new size as a (height, width) tuple, which is the reverse of the (width, height) format used by Pillow and OpenCV.

Resizing with matplotlib and NumPy

import matplotlib.pyplot as plt
from skimage.transform import resize
img = plt.imread('sample.jpg')
print(f"Original shape: {img.shape}")
resized_img = resize(img, (200, 300))
print(f"Resized shape: {resized_img.shape}")
plt.imsave('resized_sample.jpg', resized_img)--OUTPUT--Original shape: (768, 1024, 3)
Resized shape: (200, 300, 3)

While Matplotlib is famous for plotting, you can also use it for image input and output. It works seamlessly with NumPy, loading images directly into NumPy arrays using plt.imread(). This method is a bit of a hybrid approach.

  • The actual resizing isn't done by Matplotlib but by the resize function imported from skimage.transform.
  • Consistent with scikit-image's convention, the new dimensions are passed as a (height, width) tuple.
  • After resizing, you can save the resulting NumPy array as an image with plt.imsave().

Advanced image resizing techniques

Moving beyond single-image resizing, you can now tackle more practical challenges like processing entire folders, preserving image proportions, and selecting the best resizing algorithm.

Batch processing multiple images

import os
from PIL import Image

folder = 'images/'
count = 0
for filename in os.listdir(folder):
if filename.endswith(('.jpg', '.png', '.jpeg')):
img = Image.open(folder + filename)
resized_img = img.resize((300, 200))
resized_img.save(f'resized_{filename}')
count += 1
print(f"Resized {count} images to 300x200 pixels")--OUTPUT--Resized 5 images to 300x200 pixels

This script automates resizing for an entire folder of images by using Python's built-in os module. It iterates through each item in a directory, making it efficient for handling large collections. The core of this process is a loop that applies the resizing logic to every valid image it finds.

  • A conditional check using endswith() ensures that the code only attempts to process files with common image extensions.
  • Each valid image is opened and resized using the same Pillow methods as before.
  • Finally, it saves the new image with a resized_ prefix—a simple but effective way to keep your original files intact.

Maintaining aspect ratio while resizing

from PIL import Image
img = Image.open('sample.jpg')
width, height = img.size
print(f"Original size: {width}x{height}")
aspect_ratio = width / height
new_width = 300
new_height = int(new_width / aspect_ratio)
resized_img = img.resize((new_width, new_height))
print(f"Resized to: {new_width}x{new_height} (aspect ratio preserved)")--OUTPUT--Original size: 1024x768
Resized to: 300x225 (aspect ratio preserved)

Forcing an image into fixed dimensions often leads to distortion. This code avoids that by preserving the original aspect ratio. It calculates the ratio of the original width to its height, then uses that ratio to compute a new height based on a fixed width. This ensures the image scales proportionally without stretching or squishing.

  • The script first finds the aspect_ratio by dividing the original width by the height.
  • With a set new_width, the corresponding new_height is calculated using the formula new_width / aspect_ratio.
  • Finally, the result is converted to a whole number with int(), as pixel dimensions can't be fractions.

Comparing different interpolation methods

from PIL import Image
import time

img = Image.open('sample.jpg')
methods = {Image.NEAREST: "NEAREST", Image.BILINEAR: "BILINEAR", Image.LANCZOS: "LANCZOS"}

for method, name in methods.items():
start = time.time()
img.resize((300, 200), method)
print(f"{name} took {time.time() - start:.4f} seconds")--OUTPUT--NEAREST took 0.0012 seconds
BILINEAR took 0.0053 seconds
LANCZOS took 0.0187 seconds

When you resize an image, the library needs an algorithm to calculate the new pixel values. This process is called interpolation, and the method you choose affects both speed and quality. The code times three common options available in Pillow's resize() function, revealing a clear trade-off.

  • Image.NEAREST: The fastest method. It simply picks the nearest pixel, which can result in a blocky or jagged look.
  • Image.BILINEAR: A middle ground. It averages nearby pixels for a smoother result than NEAREST.
  • Image.LANCZOS: The slowest but highest-quality option. It uses a more complex formula to preserve sharpness.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. You can move from piecing together individual techniques to building complete apps with Agent 4, which takes your description and handles the code, databases, APIs, and deployment.

Instead of just resizing one image at a time, you can describe the full tool you want to build and let the Agent create it:

  • A web utility that batch-processes an uploaded folder of images, resizing them all for a uniform gallery display.
  • A thumbnail generator that automatically creates multiple image sizes from a source file while preserving the original aspect ratio.
  • An image optimization tool that lets users choose an interpolation method like LANCZOS for quality or NEAREST for speed.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

Resizing images in Python can sometimes throw errors, but most issues are straightforward to diagnose and fix with a little know-how.

Handling incorrect dimension order in resize() functions

A frequent mix-up is the dimension order required by different libraries. Pillow’s resize() and OpenCV’s cv2.resize() both expect a (width, height) tuple. However, scikit-image’s transform.resize() function flips this, requiring (height, width). Getting this wrong won't always crash your code—it will just produce an image with incorrect proportions, making it a subtle but frustrating bug. Always double-check the library's documentation to confirm the expected order.

Troubleshooting "cannot identify image file" errors

When a library like Pillow can't open a file, you'll often see a "cannot identify image file" error. This message isn't about the resizing logic itself but points to a problem with accessing the source file. The most common culprits are:

  • An incorrect file path or a typo in the filename.
  • The file is corrupted or isn't a valid image format that the library recognizes.
  • Your script doesn't have the necessary permissions to read the file from its location.

To fix this, first verify the file path is correct. Then, try opening the image in a standard viewer to ensure it's not damaged. Finally, check the file's read permissions.

Fixing color mode issues when saving resized images

If your resized image saves with strange colors or in grayscale, the issue is likely its color mode. Images can be stored in different modes, such as RGB (for screens) or CMYK (for printing). Some libraries struggle to save images that aren't in the standard RGB format. The simplest solution is to convert the image to RGB before saving. In Pillow, for example, you can call .convert('RGB') on your image object to ensure color consistency across different file formats and viewers.

Handling incorrect dimension order in resize() functions

This mistake is particularly tricky because it doesn't raise an error—it just produces a distorted image. The following code demonstrates what happens when the dimensions for Pillow's resize() function are accidentally swapped, creating an image with incorrect proportions.

from PIL import Image
img = Image.open('sample.jpg')
# Meant to be 300 width, 200 height but dimensions are flipped
resized_img = img.resize((200, 300))
resized_img.save('wrong_dimensions.jpg')

The code passes (200, 300) to resize(), mistakenly setting the width to 200 and height to 300. This creates a vertically stretched image instead of the intended wider format. The corrected implementation is shown next.

from PIL import Image
img = Image.open('sample.jpg')
# Correct order: (width, height)
resized_img = img.resize((300, 200))
resized_img.save('correct_dimensions.jpg')

The corrected code fixes the distortion by passing the dimensions in the right order. Pillow's resize() function always expects a (width, height) tuple. By providing (300, 200), the image is correctly scaled to be 300 pixels wide and 200 pixels high. This bug often appears when you switch between libraries, as scikit-image uses a (height, width) format, so it's crucial to double-check the documentation for the specific function you're using.

Troubleshooting "cannot identify image file" errors

This error pops up when Python can't locate or access your image file. It's a classic file path issue, not a bug in your resizing logic. The code below demonstrates how a simple mistake in the path passed to Image.open() causes the program to fail.

from PIL import Image
# Incorrect path or file doesn't exist
img = Image.open('images/sample.jpg')
resized_img = img.resize((300, 200))
resized_img.save('resized_sample.jpg')

The code fails because the path 'images/sample.jpg' passed to Image.open() is invalid, so the script can't find the file. This triggers the error before any resizing can occur. The corrected code shows how to fix this.

from PIL import Image
import os
# Check if file exists before attempting to open
file_path = 'images/sample.jpg'
if os.path.exists(file_path):
img = Image.open(file_path)
resized_img = img.resize((300, 200))
resized_img.save('resized_sample.jpg')
else:
print(f"Error: File {file_path} not found")

The corrected code prevents the error by first checking if the file exists using os.path.exists(). This function takes a file path and returns True if the file is found. By wrapping the Image.open() call in a conditional check, you ensure the program only tries to open files that are actually there. It's a good practice to adopt whenever your script interacts with the file system, especially when dealing with user-provided or dynamically generated file paths.

Fixing color mode issues when saving resized images

Your resized image might save with strange colors or lose features like transparency. This issue often stems from a color mode mismatch, like saving a PNG with an alpha channel into a format like JPEG that doesn't support it. The code below shows this problem in action.

from PIL import Image
img = Image.open('sample.png') # RGBA image with transparency
resized_img = img.resize((300, 200))
# This will lose transparency and may cause errors
resized_img.save('resized_sample.jpg')

The code saves a .png file, which often includes transparency, into the .jpg format. Because JPEGs don't support an alpha channel, this transparency is lost, creating unexpected visual results. The corrected implementation shows how to fix this.

from PIL import Image
img = Image.open('sample.png') # RGBA image with transparency
resized_img = img.resize((300, 200))
if img.mode == 'RGBA':
resized_img = resized_img.convert('RGB')
resized_img.save('resized_sample.jpg')

The solution first checks if the image's mode is RGBA, which indicates it has a transparency layer. If so, the code explicitly converts the image to the standard RGB format using the convert('RGB') method. This safely removes the transparency channel before saving to a format like JPEG, which doesn't support it. This step prevents color artifacts and ensures your final image looks as expected across different viewers.

Real-world applications

With the technical details covered, these resizing techniques are the backbone of many features you encounter daily online.

Creating thumbnails for web galleries

Creating thumbnails is essential for web galleries, allowing you to display many images as small previews without sacrificing performance.

from PIL import Image

img = Image.open('sample.jpg')
img.thumbnail((150, 150)) # Maintains aspect ratio
print(f"Thumbnail size: {img.size}")
img.save('sample_thumbnail.jpg')

This code uses Pillow’s thumbnail() method, a specialized function for creating image previews. It differs from resize() in two key ways:

  • It modifies the image object directly, or in-place, instead of returning a new one.
  • It automatically preserves the original aspect ratio, scaling the image down to fit within the maximum (width, height) you provide without causing distortion.

Because the operation is in-place, you can call save() on the original img object to write the newly created thumbnail to your disk.

Preparing images for social media platforms

Each social media platform has its own ideal image sizes, making automated resizing a practical way to prepare your content.

from PIL import Image

original = Image.open('profile_photo.jpg')
# Different sizes for different platforms
instagram = original.resize((180, 180))
twitter = original.resize((400, 400))
facebook = original.resize((170, 170))
instagram.save('instagram_profile.jpg')
print(f"Created profile pictures for 3 social media platforms")

This script demonstrates how to efficiently generate multiple image sizes from a single source file. It loads the original image just once using Image.open(). From there, it performs several independent resizing operations, which is a common workflow for preparing content.

  • The resize() method is called on the original object for each platform.
  • Each call returns a completely new image object in memory, leaving the original untouched.
  • Finally, save() is used to write one of the new objects to a file.

This approach is memory-efficient because you don't need to reload the source image for each new size you create.

Get started with Replit

Put these techniques into practice by building a complete tool. Just tell Replit Agent what you need, like “a web utility that batch-resizes uploaded images” or “a thumbnail generator that preserves aspect ratio.”

Replit Agent writes the code, tests for errors, and deploys the app. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.