CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pillow

Python Imaging Library (Fork) providing comprehensive image processing capabilities for reading, writing, and manipulating images across dozens of formats.

Pending
Overview
Eval results
Files

operations.mddocs/

Image Operations and Transformations

Advanced image manipulation functions including automatic contrast adjustment, color space operations, geometric transformations, and specialized processing operations provided by the ImageOps module.

Capabilities

Automatic Image Enhancement

Functions for automatic image quality improvement and adjustment.

def autocontrast(image, cutoff=0, ignore=None, mask=None, preserve_tone=False):
    """
    Maximize image contrast by stretching histogram.

    Parameters:
    - image (Image): Input image
    - cutoff (float | tuple): Percentage to cut from histogram ends (0-100)
    - ignore (int | sequence): Pixel values to ignore in histogram
    - mask (Image): Optional mask for selective processing
    - preserve_tone (bool): Preserve image tone in Photoshop-like style

    Returns:
    Image: Auto-contrast adjusted image
    """

def equalize(image, mask=None):
    """
    Equalize image histogram for improved contrast distribution.

    Parameters:
    - image (Image): Input image
    - mask (Image): Optional mask for selective equalization

    Returns:
    Image: Histogram equalized image
    """

def posterize(image, bits):
    """
    Reduce the number of bits for each color channel.

    Parameters:
    - image (Image): Input image
    - bits (int): Number of bits to keep per channel (1-8)

    Returns:
    Image: Posterized image
    """

def solarize(image, threshold=128):
    """
    Invert all pixel values above threshold (solarization effect).

    Parameters:
    - image (Image): Input image
    - threshold (int): Threshold value (0-255)

    Returns:
    Image: Solarized image
    """

Geometric Transformations and Sizing

Functions for resizing, fitting, and transforming images.

def fit(image, size, method=3, bleed=0.0, centering=(0.5, 0.5)):
    """
    Fit image within given size, cropping as needed.

    Parameters:
    - image (Image): Input image
    - size (tuple): Target size as (width, height)
    - method (int): Resampling method (Resampling.LANCZOS, etc.)
    - bleed (float): Remove a border around fitted image (0.0-0.5)
    - centering (tuple): Crop centering as (horizontal, vertical) (0.0-1.0)

    Returns:
    Image: Fitted image
    """

def contain(image, size, method=3):
    """
    Resize image to fit within size while maintaining aspect ratio.

    Parameters:
    - image (Image): Input image
    - size (tuple): Maximum size as (width, height)
    - method (int): Resampling method

    Returns:
    Image: Contained image
    """

def cover(image, size, method=3):
    """
    Resize image to cover the entire size, cropping if necessary.

    Parameters:
    - image (Image): Input image
    - size (tuple): Target size as (width, height)
    - method (int): Resampling method

    Returns:
    Image: Covered image (may be cropped)
    """

def pad(image, size, method=3, color=None, centering=(0.5, 0.5)):
    """
    Resize and pad image to exact size.

    Parameters:
    - image (Image): Input image
    - size (tuple): Target size as (width, height)
    - method (int): Resampling method
    - color (int | tuple | str): Padding color
    - centering (tuple): Image centering in padded area

    Returns:
    Image: Padded image
    """

def scale(image, factor, resample=3):
    """
    Scale image by a factor.

    Parameters:
    - image (Image): Input image
    - factor (float): Scale factor (>1 enlarges, <1 shrinks)
    - resample (int): Resampling method

    Returns:
    Image: Scaled image
    """

def crop(image, border=0):
    """
    Remove border pixels from image.

    Parameters:
    - image (Image): Input image
    - border (int | tuple): Border size to remove

    Returns:
    Image: Cropped image
    """

def expand(image, border=0, fill=0):
    """
    Add border pixels around image.

    Parameters:
    - image (Image): Input image
    - border (int | tuple): Border size to add
    - fill (int | tuple | str): Border color

    Returns:
    Image: Expanded image
    """

Color and Tone Operations

Functions for color manipulation and tone adjustment.

def colorize(image, black, white, mid=None, blackpoint=0, whitepoint=255, midpoint=127):
    """
    Colorize a grayscale image with specified colors.

    Parameters:
    - image (Image): Grayscale input image
    - black (int | tuple | str): Color for black pixels
    - white (int | tuple | str): Color for white pixels
    - mid (int | tuple | str): Color for mid-tone pixels
    - blackpoint (int): Pixel value mapped to black color (0-255)
    - whitepoint (int): Pixel value mapped to white color (0-255)
    - midpoint (int): Pixel value mapped to mid color (0-255)

    Returns:
    Image: Colorized image
    """

def grayscale(image):
    """
    Convert image to grayscale using ITU-R 601-2 luma transform.

    Parameters:
    - image (Image): Input image

    Returns:
    Image: Grayscale image
    """

def invert(image):
    """
    Invert image colors (negative effect).

    Parameters:
    - image (Image): Input image

    Returns:
    Image: Inverted image
    """

Orientation and Flipping

Functions for rotating and flipping images.

def flip(image):
    """
    Flip image vertically (top to bottom).

    Parameters:
    - image (Image): Input image

    Returns:
    Image: Vertically flipped image
    """

def mirror(image):
    """
    Flip image horizontally (left to right).

    Parameters:
    - image (Image): Input image

    Returns:
    Image: Horizontally flipped image
    """

def exif_transpose(image, in_place=False):
    """
    Transpose image according to EXIF orientation data.

    Parameters:
    - image (Image): Input image with EXIF data
    - in_place (bool): Modify image in place if True

    Returns:
    Image | None: Transposed image (or None if in_place=True)
    """

Advanced Transformations

Functions for complex geometric transformations.

def deform(image, deformer, resample=1):
    """
    Deform image using a deformer object.

    Parameters:
    - image (Image): Input image
    - deformer: Deformer object implementing getmesh() method
    - resample (int): Resampling method

    Returns:
    Image: Deformed image
    """

Usage Examples

Automatic Image Enhancement Workflow

from PIL import Image, ImageOps

def enhance_image_auto(image_path, save_path):
    """Automatically enhance an image using multiple operations."""
    img = Image.open(image_path)
    
    # Step 1: Auto contrast adjustment
    enhanced = ImageOps.autocontrast(img, cutoff=2)
    
    # Step 2: Equalize histogram for better distribution
    enhanced = ImageOps.equalize(enhanced)
    
    # Step 3: Convert to grayscale and back to remove color casts
    if img.mode == "RGB":
        gray = ImageOps.grayscale(enhanced)
        # Apply colorization to remove color casts
        enhanced = ImageOps.colorize(gray, black="black", white="white")
    
    enhanced.save(save_path)
    return enhanced

# Process an image
enhanced = enhance_image_auto("photo.jpg", "enhanced_photo.jpg")

Professional Photo Resizing

from PIL import Image, ImageOps

def resize_for_web(image_path, max_size=(800, 600), quality=85):
    """Resize image for web use with proper aspect ratio handling."""
    img = Image.open(image_path)
    
    # Method 1: Contain - fits within bounds
    contained = ImageOps.contain(img, max_size, method=Image.Resampling.LANCZOS)
    contained.save("web_contained.jpg", "JPEG", quality=quality, optimize=True)
    
    # Method 2: Cover - fills entire area, may crop
    covered = ImageOps.cover(img, max_size, method=Image.Resampling.LANCZOS)
    covered.save("web_covered.jpg", "JPEG", quality=quality, optimize=True)
    
    # Method 3: Fit with cropping control
    fitted = ImageOps.fit(img, max_size, method=Image.Resampling.LANCZOS, 
                         centering=(0.5, 0.4))  # Center horizontally, slightly above center vertically
    fitted.save("web_fitted.jpg", "JPEG", quality=quality, optimize=True)
    
    # Method 4: Pad to exact size
    padded = ImageOps.pad(img, max_size, method=Image.Resampling.LANCZOS, 
                         color="white", centering=(0.5, 0.5))
    padded.save("web_padded.jpg", "JPEG", quality=quality, optimize=True)

resize_for_web("original_photo.jpg")

Creative Color Effects

from PIL import Image, ImageOps

def create_artistic_effects(image_path):
    """Create various artistic effects using ImageOps."""
    img = Image.open(image_path)
    
    # Convert to grayscale first for colorization effects
    gray = ImageOps.grayscale(img)
    
    # Sepia tone effect
    sepia = ImageOps.colorize(gray, black="black", white="#FFF8DC", mid="#CD853F")
    sepia.save("sepia_effect.jpg")
    
    # Cool blue tone
    cool = ImageOps.colorize(gray, black="#000080", white="#E6F3FF", mid="#4169E1")
    cool.save("cool_effect.jpg")
    
    # Warm orange tone
    warm = ImageOps.colorize(gray, black="#2F1B14", white="#FFF8DC", mid="#FF8C00")
    warm.save("warm_effect.jpg")
    
    # High contrast black and white
    high_contrast = ImageOps.autocontrast(gray, cutoff=5)
    high_contrast.save("high_contrast.jpg")
    
    # Posterized effect
    posterized = ImageOps.posterize(img, bits=4)
    posterized.save("posterized.jpg")
    
    # Solarization effect
    solarized = ImageOps.solarize(img, threshold=100)
    solarized.save("solarized.jpg")
    
    # Inverted colors (negative)
    inverted = ImageOps.invert(img)
    inverted.save("inverted.jpg")

create_artistic_effects("portrait.jpg")

Batch Image Processing

from PIL import Image, ImageOps
import os
import glob

def batch_process_images(input_dir, output_dir, target_size=(1024, 768)):
    """Batch process images in a directory."""
    
    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Find all image files
    image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.tiff"]
    image_files = []
    for ext in image_extensions:
        image_files.extend(glob.glob(os.path.join(input_dir, ext)))
        image_files.extend(glob.glob(os.path.join(input_dir, ext.upper())))
    
    for image_path in image_files:
        try:
            filename = os.path.basename(image_path)
            name, ext = os.path.splitext(filename)
            
            # Open and process image
            img = Image.open(image_path)
            
            # Fix orientation based on EXIF
            if hasattr(img, '_getexif') and img._getexif():
                img = ImageOps.exif_transpose(img)
            
            # Resize while maintaining aspect ratio
            processed = ImageOps.contain(img, target_size, method=Image.Resampling.LANCZOS)
            
            # Auto-enhance
            processed = ImageOps.autocontrast(processed, cutoff=1)
            
            # Save processed image
            output_path = os.path.join(output_dir, f"{name}_processed{ext}")
            if ext.lower() in ['.jpg', '.jpeg']:
                processed.save(output_path, "JPEG", quality=90, optimize=True)
            else:
                processed.save(output_path)
            
            print(f"Processed: {filename}")
            
        except Exception as e:
            print(f"Error processing {filename}: {e}")

# Process all images in a directory
batch_process_images("input_photos", "output_photos", target_size=(800, 600))

Image Borders and Frames

from PIL import Image, ImageOps

def add_decorative_border(image_path, border_size=20, border_color="white"):
    """Add decorative border to image."""
    img = Image.open(image_path)
    
    # Simple border
    bordered = ImageOps.expand(img, border=border_size, fill=border_color)
    bordered.save("simple_border.jpg")
    
    # Fancy multi-layer border
    # Inner border
    bordered = ImageOps.expand(img, border=5, fill="black")
    # Middle border  
    bordered = ImageOps.expand(bordered, border=15, fill="white")
    # Outer border
    bordered = ImageOps.expand(bordered, border=3, fill="gray")
    bordered.save("fancy_border.jpg")
    
    # Asymmetric border (different sizes for each side)
    # Using crop with negative values adds border
    width, height = img.size
    expanded = Image.new(img.mode, (width + 100, height + 60), "lightgray")
    expanded.paste(img, (50, 20))  # Offset creates border
    expanded.save("asymmetric_border.jpg")

add_decorative_border("photo.jpg")

Smart Cropping and Composition

from PIL import Image, ImageOps

def smart_crop_portraits(image_path):
    """Demonstrate different cropping strategies for portraits."""
    img = Image.open(image_path)
    
    # Square crop for profile pictures - center on upper portion
    square_size = min(img.size)
    square = ImageOps.fit(img, (square_size, square_size), 
                         method=Image.Resampling.LANCZOS,
                         centering=(0.5, 0.3))  # Center horizontally, upper third vertically
    square.save("profile_square.jpg")
    
    # 16:9 crop for social media
    aspect_16_9 = (1920, 1080)
    social = ImageOps.fit(img, aspect_16_9, 
                         method=Image.Resampling.LANCZOS,
                         centering=(0.5, 0.4))
    # Scale down to reasonable size
    social = ImageOps.contain(social, (800, 450), method=Image.Resampling.LANCZOS)
    social.save("social_media.jpg")
    
    # 4:5 crop for Instagram
    instagram_ratio = (800, 1000)
    instagram = ImageOps.fit(img, instagram_ratio,
                           method=Image.Resampling.LANCZOS,
                           centering=(0.5, 0.35))
    instagram.save("instagram_crop.jpg")

smart_crop_portraits("portrait.jpg")

Orientation Handling

from PIL import Image, ImageOps

def handle_image_orientation(image_path):
    """Properly handle image orientation using EXIF data."""
    img = Image.open(image_path)
    
    print(f"Original size: {img.size}")
    print(f"Original mode: {img.mode}")
    
    # Check for EXIF orientation data
    if hasattr(img, '_getexif') and img._getexif():
        exif = img._getexif()
        if exif and 274 in exif:  # 274 is the orientation tag
            orientation = exif[274]
            print(f"EXIF orientation: {orientation}")
    
    # Fix orientation automatically
    corrected = ImageOps.exif_transpose(img)
    if corrected is not None:
        print(f"Corrected size: {corrected.size}")
        corrected.save("orientation_corrected.jpg")
    else:
        print("No orientation correction needed")
        img.save("orientation_corrected.jpg")
    
    # Manual orientation operations
    flipped_v = ImageOps.flip(img)  # Vertical flip
    flipped_h = ImageOps.mirror(img)  # Horizontal flip
    
    flipped_v.save("flipped_vertical.jpg")
    flipped_h.save("flipped_horizontal.jpg")

handle_image_orientation("photo_with_exif.jpg")

Image Quality Enhancement Pipeline

from PIL import Image, ImageOps

def enhance_image_quality(image_path, output_path):
    """Professional image enhancement pipeline."""
    img = Image.open(image_path)
    
    # Step 1: Fix orientation
    img = ImageOps.exif_transpose(img) or img
    
    # Step 2: Crop unwanted borders (remove 1% from each edge)
    width, height = img.size
    crop_amount = min(width, height) * 0.01
    img = ImageOps.crop(img, border=int(crop_amount))
    
    # Step 3: Gentle auto-contrast (preserve most of the original look)
    img = ImageOps.autocontrast(img, cutoff=0.5)
    
    # Step 4: Subtle histogram equalization on luminance only
    if img.mode == "RGB":
        # Convert to HSV, equalize V channel, convert back
        import colorsys
        # This is a simplified approach - in practice you'd use proper color space conversion
        img = ImageOps.autocontrast(img, cutoff=1.0)
    
    # Step 5: Resize to target resolution if needed
    max_dimension = 2048
    if max(img.size) > max_dimension:
        img = ImageOps.contain(img, (max_dimension, max_dimension), 
                              method=Image.Resampling.LANCZOS)
    
    # Save with optimal quality
    img.save(output_path, "JPEG", quality=95, optimize=True)
    return img

# Enhance image quality
enhanced = enhance_image_quality("raw_photo.jpg", "enhanced_photo.jpg")

Install with Tessl CLI

npx tessl i tessl/pypi-pillow

docs

color-management.md

color-utilities.md

core-image.md

drawing.md

enhancement.md

filters.md

fonts.md

image-sequences.md

image-statistics.md

index.md

math-operations.md

operations.md

tile.json