How to resize an image in Python

Learn to resize images in Python. This guide covers various 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: 
Thu
Mar 5, 2026
The Replit Team Logo Image
The Replit Team

The ability to resize an image in Python is a key skill for web development and data augmentation. Popular libraries provide simple methods to alter image dimensions with both speed and accuracy.

In this article, you'll explore several techniques to resize images with popular libraries. You'll get practical tips, review real-world applications, and receive clear advice to debug common problems you might face in your projects.

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 Pillow library's Image.resize() method is a straightforward way to change an image's dimensions. It requires a tuple specifying the new width and height, like (300, 200). The function returns a completely new image object, which is why the code saves it to a new file. Your original image isn't altered.

It's important to note that resize() forces the image into the new dimensions. This can distort the image if the new aspect ratio doesn't match the original. This method is best used when you need an image of an exact size, regardless of potential stretching or squashing.

Popular libraries for image resizing

While Pillow provides a straightforward method, libraries like OpenCV, scikit-image, and Matplotlib offer more specialized functions for handling different resizing scenarios you might encounter.

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 is a popular choice for computer vision tasks, and its cv2.resize() function is highly efficient. Unlike Pillow, OpenCV represents images as NumPy arrays. This means you'll use the shape attribute to get an image's dimensions.

  • The img.shape attribute returns dimensions in (height, width, channels) order.
  • Note that the cv2.resize() function requires the new size as a (width, height) tuple—the reverse of how shape reports it.

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 is another powerful library for image processing, and its transform.resize() function is quite intuitive. It also works with NumPy arrays, so you'll use the shape attribute to check dimensions. The key thing to remember is how it handles the new size.

  • The transform.resize() function expects the output dimensions as a (height, width) tuple.
  • This is the reverse of both Pillow and OpenCV, which require a (width, height) tuple.
  • It also returns a floating-point image with pixel values scaled between 0 and 1, which is important for further processing.

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 known for plotting, you can also use it for basic image tasks. The plt.imread() function loads your image as a NumPy array, which you can see from the shape attribute. The key thing here is that Matplotlib doesn't have its own resize function—this example actually uses resize from scikit-image to do the work.

  • As with the previous scikit-image example, the function expects the new size as a (height, width) tuple.

Finally, plt.imsave() saves the modified array as a new image.

Advanced image resizing techniques

Moving beyond the basics, you can refine your resizing workflow to handle multiple images, maintain the original aspect ratio, and select the best interpolation 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

When you need to resize many images, a script is far more efficient than manual editing. This code automates the process by using Python's os module to work through an entire directory. It's a common workflow for preparing image datasets or standardizing web assets.

  • The script loops through every item in a folder with os.listdir().
  • An if statement filters for files with common image extensions like .jpg or .png.
  • Each matched image is then opened, resized, and saved with a new filename.

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)

To avoid distorting your image, the code first calculates the original aspect ratio. It does this by dividing the image's width by its height. This simple calculation is the key to keeping the image's proportions intact when you change its size.

  • Once you define a new_width, the script calculates the corresponding height by dividing the new width by the original aspect_ratio.
  • The result is wrapped in int() because pixel dimensions must be whole numbers, ensuring the final size is valid for the resize() method.

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

Interpolation algorithms determine how an image's pixels are recalculated when you resize it. The code demonstrates that your choice of method in resize() creates a trade-off between speed and quality. As you can see from the output, some methods are much faster than others.

  • Image.NEAREST is the fastest but can produce blocky, pixelated results.
  • Image.BILINEAR offers a balance, creating smoother images than NEAREST.
  • Image.LANCZOS provides the highest quality but is also the slowest, making it ideal when image detail is the top priority.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the image resizing techniques we've explored, Replit Agent can turn them into production-ready tools:

  • Build an automatic thumbnail generator that processes an entire folder of images for a web gallery.
  • Create a profile picture utility that resizes uploads to a fixed width while preserving the aspect ratio.
  • Deploy a social media asset creator that converts a single image into multiple sizes for different platforms, optimizing for quality with the right interpolation.

Describe your app idea, and you can watch Replit Agent write the code, test it, and handle deployment automatically, all within your browser.

Common errors and challenges

Resizing images can sometimes lead to confusing errors, but understanding the common pitfalls makes them much easier to solve.

Handling incorrect dimension order in resize() functions

A frequent source of confusion is the dimension order required by different resize() functions. It's easy to mix up width and height, which can lead to unexpectedly squashed or stretched images. This happens because libraries follow different conventions.

  • Pillow and OpenCV expect dimensions as a (width, height) tuple.
  • Scikit-image, however, aligns with NumPy's array indexing and requires (height, width).

If your resized image looks wrong, the first thing to check is whether you've supplied the dimensions in the correct order for the library you're using.

Troubleshooting "cannot identify image file" errors

The "cannot identify image file" error usually points to a problem with the file path or the file itself. Your script might not be able to find the image where it's looking, or the file might be unreadable. To fix this, first verify that the file path is correct and that there are no typos in the filename. If the path is correct, try opening the image in a viewer to ensure it isn't corrupted. Using absolute paths or constructing them with os.path.join() can also help prevent path-related issues, especially in larger projects.

Fixing color mode issues when saving resized images

Sometimes, you'll successfully resize an image only to get an error when you try to save it. This often happens due to incompatible color modes. For example, trying to save an image with a transparency channel (an 'RGBA' mode) as a JPEG, which doesn't support transparency, can cause a crash. The solution is to convert the image to a compatible mode before saving. With the Pillow library, you can use the convert('RGB') method on your image object. This standardizes the image to the Red-Green-Blue color model, which is compatible with most common file formats like JPEG.

Handling incorrect dimension order in resize() functions

Getting the width and height mixed up in a resize() function is a classic error that will stretch or squash your image. It’s an easy mistake to make. The code below shows exactly what this distortion looks like in practice.

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 intended a 300-pixel width but passed the dimensions as (200, 300) to resize(). This simple mix-up forces the image into the wrong aspect ratio, causing visible distortion. The following example shows how to correct this.

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 fix is simple: ensure the dimensions you pass to resize() are in the correct (width, height) order. The corrected code provides the tuple as (300, 200), producing an image with the intended dimensions and avoiding distortion. This is a common slip-up, especially when you're switching between different image processing libraries, as they don't all follow the same convention. Always double-check the library's documentation to confirm the expected order.

Troubleshooting "cannot identify image file" errors

The Image.open() function will raise an error if it can't locate or read your file. This is usually due to a simple typo in the path or filename. The following code snippet triggers this exact error with an incorrect path.

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 directs Image.open() to look inside an images folder, but the script can't find the file at that location. This path mismatch is what triggers the error. The following example shows how to fix it.

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 fix is to confirm the file exists before your script tries to open it. By wrapping the operation in an if os.path.exists(file_path): check, you can handle the problem gracefully instead of letting the program crash. This simple validation is a good habit, especially when you're moving scripts around or working in projects with deep folder structures where file paths can easily get mixed up. It ensures your code anticipates the problem.

Fixing color mode issues when saving resized images

Saving a resized image can fail if its color mode is incompatible with the new file format. For instance, JPEGs don't support transparency, so saving a PNG with an alpha channel (RGBA mode) as a .jpg will cause problems. The following code demonstrates this exact error.

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 attempts to save the image as a .jpg, but the original PNG's transparency data can't be stored in this format, which often triggers an error. The following example shows how to handle this conversion correctly.

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 is to explicitly convert the image to a compatible color mode. By checking if the img.mode is RGBA, the code identifies images with transparency. If so, it uses the convert('RGB') method to strip out the alpha channel. This ensures the image can be saved as a JPEG without causing an error. You should watch for this issue whenever your workflow involves converting file types, especially from PNGs to JPEGs.

Real-world applications

With a solid grasp of resizing techniques and error handling, you're ready to build practical, real-world applications.

Creating thumbnails for web galleries

The Pillow library’s thumbnail() method is ideal for this task, as it resizes an image to fit within a bounding box while automatically preserving the original aspect ratio.

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')

The thumbnail() method offers a smart way to create smaller image versions. It's different from resize() because it modifies the image object directly—it doesn't return a new one. You give it a tuple like (150, 150) that acts as a maximum size constraint.

  • The function scales the image down proportionally to fit within that boundary.
  • This ensures the original aspect ratio is kept, preventing any distortion.
  • It's an efficient choice for tasks like generating gallery previews where you need to avoid stretching the image.

Preparing images for social media platforms

Each social media platform has its own ideal image sizes for profile pictures and posts, so you can use a simple script to generate all the required versions from a single source image.

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 shows an efficient workflow for creating multiple image versions. After loading the original image, it calls the resize() method on that same source object three separate times. This is a key detail—you're not resizing an already-resized image, which helps maintain quality.

  • Each resize() call returns a new, independent image object in memory.
  • Notice that while three versions are generated, the code only saves the Instagram one with instagram.save(). The other two exist only temporarily.

Get started with Replit

Turn these techniques into a real tool. Tell Replit Agent to “build a web app that generates 150x150 thumbnails from an image folder” or “create a utility that resizes a photo for social media posts.”

The agent will write the code, test for errors, and deploy your application for you. Start building with Replit and bring your idea to life.

Get started free

Create and 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.

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.