For most repeatable, scriptable work, a short Python script using Pillow is the best choice. Use a CLI like Rysize or Imgtool when you just want speed. This ten-step guide gets you from zero to a safe batch resizer on the command line, covering prerequisites, a minimal Pillow script, resizing strategies, CLI usage, edge cases, and a quick test workflow so you can run a sample resize in minutes.

1. Install prerequisites

Start with Python 3 and a few libraries. Install Pillow, the actively maintained fork of PIL, with Pip install Pillow. That's the simplest path for local, script-driven resizing and is the explicit recommendation in several how-tos including KishStats and Cloudinary.

If your work needs more advanced computer vision or custom interpolation and cropping, use OpenCV, which Cloudinary describes as a strong library for advanced image processing. If you pick a tool that wraps ImageMagick, install ImageMagick first. The imgtool repository lists common commands: Brew install imagemagick on macOS, Sudo apt-get install imagemagick on Debian or Ubuntu, and Sudo yum install ImageMagick on CentOS or RHEL.

Practical tip: if you plan to try third-party CLIs, create a virtual environment first. The rysize project recommends installing inside a virtualenv and installing the package with Pip install . from the repo directory to avoid system-level dependency conflicts.

2. Pick the right approach for you

There are two durable patterns. Pattern A is a small Python script that uses Pillow to open files, resize or thumbnail them, and save results into an output directory.

Pattern B is a command-line utility built for batch work: Rysize is a Python-based CLI built with Click and Pillow, while Imgtool is a wrapper around ImageMagick for quick resizing, compression, and reporting.

Choose Pattern A when you want full control over behavior inside a script, such as conditional resizing, metadata handling, or custom cropping logic. Choose Pattern B when you prefer a documented, single-command workflow with flags for width, height, quality, and reporting. The tradeoff is simple: scripts give flexibility, CLIs give speed and convenience.

3. The minimal Pillow script, step by step

Here is the skeleton every guide converges on. KishStats demonstrates this anatomy clearly.

First, place your source images in a single input folder and decide an output folder name. In code, import Os and From PIL import Image. Build a full input path such as Full_input_dir = os.getcwd() + '/' + input_dir and check for the output folder with Os.path.exists, creating it with Os.mkdir if needed.

Second, loop over files with For file in os.listdir(full_input_dir). Wrap file access in a try-except that catches OSError to handle missing files or permission errors. Filter by extension before calling Image.open to avoid attempting to open non-image files. Cloudinary documents the core APIs you will use inside that loop: Image.open('myimage.jpg') returns an Image object, Image.resize((width, height)) produces a new Image instance with the exact dimensions you specify, and New_image.save('out.jpg') writes the file.

Here is a short worked example scenario. You want to limit images to a 400-pixel box while preserving aspect ratio. Inside the loop call Image.thumbnail((400, 400)); that modifies the Image object to fit within the box and won't upscale images smaller than the requested size. Then save the result into your output folder, for example New_image.save('resized/out.jpg', quality=85) if you want smaller JPEG files.

4. Resizing strategies and image quality

Decide the resizing goal before you write code. Three common strategies recur in the sources.

First, target exact dimensions. Use Image.resize((width, height)) to force a specific pixel width and height. That produces exact output sizes but can distort images if input aspect ratios vary. Use a centered crop after resizing if you must produce an exact-framed thumbnail.

Point is, second, preserve aspect ratio. Use Image.thumbnail((max_width, max_height)), which scales down to fit within the box and never upscales. Cloudinary and KishStats both call out Thumbnail for ratio-preserving limits. This is the most common sensible default for web images.

Third, scale by percentage. Multiply width and height by a percentage and call Resize with the new integer dimensions. Use this when you need a proportional size reduction across all files.

For file-size control add JPEG quality settings when saving. The brief examples use New_image.save('out.jpg', quality=85) to reduce file size. Remember that Quality=100 gives maximal JPEG fidelity at the cost of larger files.

If your workflow requires precise cropping or advanced interpolation, consider OpenCV or ImageMagick. OpenCV is the stronger choice for machine-vision style pre-processing, while ImageMagick, accessed directly or via Imgtool, excels at scripted conversions, combined resize-and-compress operations, and batch reporting.

If you prefer a single command, the field has good options. The Rysize project exposes flags for path, width, height, ratio, and more. A typical usage example is Rysize --width 800 --path /home/user/containing-folder. If you omit the path rysize prompts for it. Rysize maintains aspect ratio by default and supports jpg, jpeg, png, bmp and gif. The rysize authors recommend testing inside a virtualenv, and they note the tool was tested on Linux.

The Imgtool repository wraps ImageMagick for quick operations and reporting. Its README shows commands such as Imgtool --dimensions photo.jpg for a quick check, Imgtool --compress photo.jpg 85 to set JPEG quality, and Imgtool --resize-in-place photo.jpg 1200 for resizing in place. Imgtool supports combined resize-and-compress operations and includes an installer script that can place the binary in ~/bin and add it to your PATH.

Choose rysize when you want a Python-native, Pillow-backed CLI with aspect-ratio safety and straightforward flags. Choose imgtool when ImageMagick is already part of your stack and you want advanced conversion features and file-size reporting out of the box.

All sources recommend the same simple layout. Put source images in a single input folder. Write outputs to a dedicated output folder. That keeps originals untouched and makes it easy to run multiple passes with different settings.

Inspireme.blog gives two practical options: move your script into the folder with your images and run it there, or change the script's input folder variable and run the script from your current working directory. KishStats shows building paths relative to Os.getcwd(), which is robust when you execute the script from different places. Test runs should use a small representative subset of files first so you can confirm naming, format preservation, and visual quality before processing thousands of images.

Make your script tolerant. Wrap file IO in try-except blocks to catch OSError and related errors. Filter input files by extension to avoid attempting to open non-image files, and skip or log files that fail to open rather than crashing the whole run. KishStats demonstrates these defensive patterns in its examples.

Decide how to deal with images that are already smaller than your target. Remember that Thumbnail won't upscale, which may be desirable if you want to avoid degrading small source images. If you need every output to be the same pixel size, put in place an explicit upscale or pad step in your script, or use ImageMagick features via imgtool for controlled upscaling.

Check CLI overwrite behavior. Rysize creates new files in an output folder by default. Imgtool documents an overwrite option for in-place operations. Confirm which mode you want before a large run, and keep backups of originals if you might overwrite them.

For large batches include logging and size reporting so you can verify gains. Imgtool includes file-size reporting features so you can see percentage reduction across a set. If integrating into CI or server-side automation prefer a direct library call from a script or an ImageMagick-backed CLI depending on runtime constraints.

Cloudinary offers an alternative route: hosted API resizing and cropping. If you prefer cloud automation for production image delivery, Cloudinary documents using its service for automated resizing and cropping instead of running local jobs. Use that when you want hosted scaling, not local batch processing.

On Windows run Python from a command prompt, change directory to the folder with Cd "C:\path\to\folder", and run Python resize_images.py, as inspireme.blog shows. On macOS and Linux you will normally use a Bash shell. Imgtool and rysize expect a Unix-like shell for installer steps. If you install ImageMagick system-wide on Linux you may need Sudo. The rysize authors specifically recommend a virtualenv to avoid system-level dependency issues.

Follow these steps as a checklist. First, install Pillow. Second, create a small test folder with representative images. Third, run your script or CLI on that sample with settings for width, height, or quality. Fourth, inspect results for aspect ratio, edge artifacts, and file size. Fifth, run the batch on the full input folder when you are satisfied. This mirrors the workflow described across the sources and prevents surprises when you process thousands of files.

I'll save you the trouble: back up originals before you run any in-place operation. That single habit avoids the most common regret.

1. Install Pillow with Pip install Pillow, or install ImageMagick with Brew install imagemagick or Sudo apt-get install imagemagick when using imgtool.

2. Choose a short Pillow script for control or rysize/imgtool for one-command batch work.

3. Test on a small folder, check aspect ratio and quality, then run your full batch with originals backed up.

4. Use Image.thumbnail to preserve aspect ratio and avoid upscaling. Add Quality=85 when saving JPEGs to reduce file size.

5. Log and report file-size reduction for large runs or use Cloudinary if you want hosted automation instead of local processing.

Related Articles

Concrete next step: run Pip install Pillow, create an images folder with a handful of files, and execute a minimal script that opens each file with Image.open, calls Image.thumbnail((400, 400)) to preserve aspect ratio or Image.resize((500, 500)) to force dimensions, and saves outputs into a resized folder. Or, if you prefer a one-line CLI, install Rysize inside a virtualenv and try Rysize --width 800 --path /home/user/containing-folder as a safe test.

This article was created with AI assistance.