Python Snippets

Automatic Image Resizer with Aspect Ratio Preservation

from PIL import Image
import os
import argparse

def resize_image(input_path, output_path, target_width, target_height, quality=85):
    """
    Resize an image while preserving its aspect ratio and maintaining quality.
    
    Args:
        input_path (str): Path to the input image file
        output_path (str): Path where resized image will be saved
        target_width (int): Desired width of the output image
        target_height (int): Desired height of the output image
        quality (int): JPEG quality (1-100, higher is better quality)
    
    Returns:
        bool: True if successful, False otherwise
    """
    try:
        # Open the image
        with Image.open(input_path) as img:
            # Calculate aspect ratios
            original_ratio = img.width / img.height
            target_ratio = target_width / target_height
            
            # Determine new dimensions based on aspect ratio
            if original_ratio > target_ratio:
                # Image is wider than target ratio
                new_width = target_width
                new_height = int(target_width / original_ratio)
            else:
                # Image is taller than target ratio
                new_height = target_height
                new_width = int(target_height * original_ratio)
            
            # Resize the image with high quality resampling
            resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
            
            # Save with appropriate format
            if output_path.lower().endswith(('.jpg', '.jpeg')):
                # For JPEG, convert to RGB if necessary
                if resized_img.mode in ('RGBA', 'LA', 'P'):
                    resized_img = resized_img.convert('RGB')
                resized_img.save(output_path, 'JPEG', quality=quality, optimize=True)
            else:
                # For other formats, preserve original mode
                resized_img.save(output_path, optimize=True)
            
            return True
    except Exception as e:
        print(f"Error processing {input_path}: {str(e)}")
        return False

def batch_resize_images(input_dir, output_dir, width, height, quality=85):
    """
    Resize all images in a directory to specified dimensions.
    
    Args:
        input_dir (str): Directory containing input images
        output_dir (str): Directory where resized images will be saved
        width (int): Target width for resized images
        height (int): Target height for resized images
        quality (int): JPEG quality (1-100)
    """
    # Supported image formats
    supported_formats = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp')
    
    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Process each image in the input directory
    processed = 0
    for filename in os.listdir(input_dir):
        if filename.lower().endswith(supported_formats):
            input_path = os.path.join(input_dir, filename)
            output_path = os.path.join(output_dir, filename)
            
            if resize_image(input_path, output_path, width, height, quality):
                print(f"Processed: {filename}")
                processed += 1
            else:
                print(f"Failed to process: {filename}")
    
    print(f"\nCompleted! Processed {processed} images.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Resize images while preserving aspect ratio")
    parser.add_argument("input", help="Input image file or directory")
    parser.add_argument("output", help="Output image file or directory")
    parser.add_argument("width", type=int, help="Target width")
    parser.add_argument("height", type=int, help="Target height")
    parser.add_argument("--quality", type=int, default=85, help="JPEG quality (1-100)")
    
    args = parser.parse_args()
    
    # Check if input is a file or directory
    if os.path.isfile(args.input):
        # Single file processing
        if resize_image(args.input, args.output, args.width, args.height, args.quality):
            print("Image resized successfully!")
        else:
            print("Failed to resize image.")
    elif os.path.isdir(args.input):
        # Batch processing
        batch_resize_images(args.input, args.output, args.width, args.height, args.quality)
    else:
        print("Invalid input path specified.")

What This Code Does

This Python script provides an automatic image resizing solution that preserves the aspect ratio of images while scaling them to target dimensions. It intelligently calculates the best fit within your specified width and height constraints, ensuring that images are never distorted.

The script includes two main functions:

  1. resize_image() - Resizes a single image file
  2. batch_resize_images() - Processes all images in a directory

Key features include:

Why This is Useful

Image resizing is a common requirement in web development, content management, and digital asset organization. This tool eliminates the manual work of resizing images one by one while ensuring professional quality results. It’s particularly helpful for:

How to Run

  1. First, install the required dependency:
    pip install Pillow
    
  2. For a single image:
    python image_resizer.py input.jpg output.jpg 800 600
    
  3. For batch processing a directory:
    python image_resizer.py /path/to/input/folder /path/to/output/folder 800 600
    
  4. With custom JPEG quality:
    python image_resizer.py input.jpg output.jpg 1920 1080 --quality 90
    

The script will automatically preserve the aspect ratio of your images, so if you specify 800x600 as your target dimensions, a landscape image will fit within those constraints while maintaining its original proportions.