12 KiB
12 KiB
ImageMagick Batch Processing
Complete guide to batch operations, mogrify command, parallel processing, and automation.
Mogrify Command
Basic Mogrify
Modify files in-place (overwrites originals).
# Resize all JPEGs
mogrify -resize 800x600 *.jpg
# Convert format (creates new files)
mogrify -format png *.jpg
# Apply effect to all images
mogrify -quality 85 -strip *.jpg
Warning: mogrify modifies files in-place. Always backup originals or use -path to output to different directory.
Output to Different Directory
Preserve originals.
# Create output directory first
mkdir output
# Process to output directory
mogrify -path ./output -resize 800x600 *.jpg
# With format conversion
mogrify -path ./optimized -format webp -quality 80 *.png
Common Batch Operations
Resize All Images
# Resize to width 800
mogrify -resize 800x *.jpg
# Resize to height 600
mogrify -resize x600 *.jpg
# Fit within 800×600
mogrify -resize 800x600 *.jpg
# Resize to exact dimensions
mogrify -resize 800x600! *.jpg
# Only shrink, never enlarge
mogrify -resize 800x600\> *.jpg
Format Conversion
# PNG to JPEG
mogrify -path ./jpg -format jpg -quality 85 *.png
# JPEG to WebP
mogrify -path ./webp -format webp -quality 80 *.jpg
# Any format to PNG
mogrify -path ./png -format png *.{jpg,gif,bmp}
Optimize Images
# Strip metadata from all JPEGs
mogrify -strip *.jpg
# Optimize JPEGs for web
mogrify -quality 85 -strip -interlace Plane *.jpg
# Compress PNGs
mogrify -quality 95 *.png
# Combined optimization
mogrify -quality 85 -strip -interlace Plane -sampling-factor 4:2:0 *.jpg
Apply Effects
# Add watermark to all images
mogrify -gravity southeast -draw "image over 10,10 0,0 'watermark.png'" *.jpg
# Convert all to grayscale
mogrify -colorspace Gray *.jpg
# Apply sepia tone
mogrify -sepia-tone 80% *.jpg
# Sharpen all images
mogrify -sharpen 0x1 *.jpg
Thumbnail Generation
# Create square thumbnails
mogrify -path ./thumbnails -resize 200x200^ -gravity center -extent 200x200 *.jpg
# Create thumbnails with max dimension
mogrify -path ./thumbs -thumbnail 300x300 *.jpg
# Thumbnails with quality control
mogrify -path ./thumbs -thumbnail 200x200 -quality 80 -strip *.jpg
Shell Loops
Basic For Loop
More control than mogrify.
# Resize with custom naming
for img in *.jpg; do
magick "$img" -resize 800x600 "resized_$img"
done
# Process to subdirectory
mkdir processed
for img in *.jpg; do
magick "$img" -resize 1920x1080 "processed/$img"
done
Multiple Operations
# Complex processing pipeline
for img in *.jpg; do
magick "$img" \
-resize 1920x1080^ \
-gravity center \
-crop 1920x1080+0+0 +repage \
-unsharp 0x1 \
-quality 85 -strip \
"processed_$img"
done
Format Conversion with Rename
# Convert PNG to JPEG with new names
for img in *.png; do
magick "$img" -quality 90 "${img%.png}.jpg"
done
# Add prefix during conversion
for img in *.jpg; do
magick "$img" -resize 800x "web_${img}"
done
Conditional Processing
# Only process large images
for img in *.jpg; do
width=$(identify -format "%w" "$img")
if [ $width -gt 2000 ]; then
magick "$img" -resize 2000x "resized_$img"
fi
done
# Skip existing output files
for img in *.jpg; do
output="output_$img"
if [ ! -f "$output" ]; then
magick "$img" -resize 800x "$output"
fi
done
Parallel Processing
GNU Parallel
Process multiple images simultaneously.
# Install GNU Parallel
# Ubuntu/Debian: sudo apt-get install parallel
# macOS: brew install parallel
# Basic parallel resize
parallel magick {} -resize 800x600 resized_{} ::: *.jpg
# Parallel with function
resize_image() {
magick "$1" -resize 1920x1080 -quality 85 "processed_$1"
}
export -f resize_image
parallel resize_image ::: *.jpg
# Limit concurrent jobs
parallel -j 4 magick {} -resize 800x {} ::: *.jpg
# Progress indicator
parallel --progress magick {} -resize 800x {} ::: *.jpg
Xargs Parallel
# Using xargs for parallel processing
ls *.jpg | xargs -I {} -P 4 magick {} -resize 800x processed_{}
# With find
find . -name "*.jpg" -print0 | \
xargs -0 -I {} -P 4 magick {} -resize 800x {}
Advanced Batch Patterns
Recursive Processing
# Process all JPEGs in subdirectories
find . -name "*.jpg" -exec magick {} -resize 800x {} \;
# With output directory structure
find . -name "*.jpg" -type f | while read img; do
outdir="output/$(dirname "$img")"
mkdir -p "$outdir"
magick "$img" -resize 800x "$outdir/$(basename "$img")"
done
Batch with Different Sizes
# Generate multiple sizes
for size in 320 640 1024 1920; do
mkdir -p "output/${size}w"
for img in *.jpg; do
magick "$img" -resize ${size}x -quality 85 "output/${size}w/$img"
done
done
# Parallel version
for size in 320 640 1024 1920; do
mkdir -p "output/${size}w"
parallel magick {} -resize ${size}x -quality 85 "output/${size}w/{}" ::: *.jpg
done
Responsive Image Set
# Create responsive image set with srcset
mkdir -p responsive
for img in *.jpg; do
base="${img%.jpg}"
for width in 320 640 1024 1920; do
magick "$img" -resize ${width}x -quality 85 \
"responsive/${base}-${width}w.jpg"
done
done
Watermark Batch
# Add watermark to all images
for img in *.jpg; do
magick "$img" watermark.png \
-gravity southeast -geometry +10+10 \
-composite "watermarked_$img"
done
# Different watermark positions for portrait vs landscape
for img in *.jpg; do
width=$(identify -format "%w" "$img")
height=$(identify -format "%h" "$img")
if [ $width -gt $height ]; then
# Landscape
magick "$img" watermark.png -gravity southeast -composite "marked_$img"
else
# Portrait
magick "$img" watermark.png -gravity south -composite "marked_$img"
fi
done
Error Handling
Check Before Processing
# Verify image before processing
for img in *.jpg; do
if identify "$img" > /dev/null 2>&1; then
magick "$img" -resize 800x "processed_$img"
else
echo "Skipping corrupt image: $img"
fi
done
Log Processing
# Log successful and failed operations
log_file="batch_process.log"
error_log="errors.log"
for img in *.jpg; do
if magick "$img" -resize 800x "output/$img" 2>> "$error_log"; then
echo "$(date): Processed $img" >> "$log_file"
else
echo "$(date): Failed $img" >> "$error_log"
fi
done
Dry Run Mode
# Test without modifying files
dry_run=true
for img in *.jpg; do
cmd="magick $img -resize 800x processed_$img"
if [ "$dry_run" = true ]; then
echo "Would run: $cmd"
else
eval $cmd
fi
done
Optimization Workflows
Web Publishing Pipeline
# Complete web optimization workflow
mkdir -p web/{original,optimized,thumbnails}
# Copy originals
cp *.jpg web/original/
# Create optimized versions
mogrify -path web/optimized \
-resize 1920x1080\> \
-quality 85 \
-strip \
-interlace Plane \
web/original/*.jpg
# Create thumbnails
mogrify -path web/thumbnails \
-thumbnail 300x300 \
-quality 80 \
-strip \
web/original/*.jpg
Archive to Web Conversion
# Convert high-res archives to web formats
for img in archives/*.jpg; do
base=$(basename "$img" .jpg)
# Full size web version
magick "$img" -resize 2048x2048\> -quality 90 -strip "web/${base}.jpg"
# Thumbnail
magick "$img" -thumbnail 400x400 -quality 85 "web/${base}_thumb.jpg"
# WebP version
magick "$img" -resize 2048x2048\> -quality 85 "web/${base}.webp"
done
Print to Web Workflow
# Convert print-ready images to web
for img in print/*.tif; do
base=$(basename "$img" .tif)
# Convert colorspace and optimize
magick "$img" \
-colorspace sRGB \
-resize 2000x2000\> \
-quality 90 \
-strip \
-interlace Plane \
"web/${base}.jpg"
done
Batch Reporting
Generate Report
# Create processing report
report="batch_report.txt"
echo "Batch Processing Report - $(date)" > "$report"
echo "================================" >> "$report"
total=0
success=0
failed=0
for img in *.jpg; do
((total++))
if magick "$img" -resize 800x "output/$img" 2>/dev/null; then
((success++))
echo "✓ $img" >> "$report"
else
((failed++))
echo "✗ $img" >> "$report"
fi
done
echo "" >> "$report"
echo "Total: $total, Success: $success, Failed: $failed" >> "$report"
Image Inventory
# Create inventory of images
inventory="image_inventory.csv"
echo "Filename,Width,Height,Format,Size,ColorSpace" > "$inventory"
for img in *.{jpg,png,gif}; do
[ -f "$img" ] || continue
info=$(identify -format "%f,%w,%h,%m,%b,%[colorspace]" "$img")
echo "$info" >> "$inventory"
done
Performance Tips
Optimize Loop Performance
# Bad: Launch mogrify for each file
for img in *.jpg; do
mogrify -resize 800x "$img"
done
# Good: Process all files in one mogrify call
mogrify -resize 800x *.jpg
# Best: Use parallel processing for complex operations
parallel magick {} -resize 800x -quality 85 processed_{} ::: *.jpg
Memory Management
# Limit memory for batch processing
for img in *.jpg; do
magick -limit memory 2GB -limit map 4GB \
"$img" -resize 50% "output/$img"
done
Progress Tracking
# Show progress for long batch operations
total=$(ls *.jpg | wc -l)
current=0
for img in *.jpg; do
((current++))
echo "Processing $current/$total: $img"
magick "$img" -resize 800x "output/$img"
done
Automation Scripts
Complete Bash Script
#!/bin/bash
# Configuration
INPUT_DIR="./input"
OUTPUT_DIR="./output"
QUALITY=85
MAX_WIDTH=1920
THUMBNAIL_SIZE=300
# Create output directories
mkdir -p "$OUTPUT_DIR"/{full,thumbnails}
# Process images
echo "Processing images..."
for img in "$INPUT_DIR"/*.{jpg,jpeg,png}; do
[ -f "$img" ] || continue
filename=$(basename "$img")
base="${filename%.*}"
# Full size
magick "$img" \
-resize ${MAX_WIDTH}x\> \
-quality $QUALITY \
-strip \
"$OUTPUT_DIR/full/${base}.jpg"
# Thumbnail
magick "$img" \
-thumbnail ${THUMBNAIL_SIZE}x${THUMBNAIL_SIZE} \
-quality 80 \
-strip \
"$OUTPUT_DIR/thumbnails/${base}_thumb.jpg"
echo "✓ $filename"
done
echo "Done!"
Python Batch Script
#!/usr/bin/env python3
import os
import subprocess
from pathlib import Path
INPUT_DIR = Path("./input")
OUTPUT_DIR = Path("./output")
SIZES = [320, 640, 1024, 1920]
# Create output directories
for size in SIZES:
(OUTPUT_DIR / f"{size}w").mkdir(parents=True, exist_ok=True)
# Process images
for img in INPUT_DIR.glob("*.jpg"):
for size in SIZES:
output = OUTPUT_DIR / f"{size}w" / img.name
subprocess.run([
"magick", str(img),
"-resize", f"{size}x",
"-quality", "85",
"-strip",
str(output)
])
print(f"✓ {img.name} -> {size}w")
Common Batch Recipes
Social Media Sizes
# Generate social media image sizes
for img in *.jpg; do
base="${img%.jpg}"
# Instagram square (1080×1080)
magick "$img" -resize 1080x1080^ -gravity center -extent 1080x1080 "${base}_ig_square.jpg"
# Instagram portrait (1080×1350)
magick "$img" -resize 1080x1350^ -gravity center -extent 1080x1350 "${base}_ig_portrait.jpg"
# Facebook post (1200×630)
magick "$img" -resize 1200x630^ -gravity center -extent 1200x630 "${base}_fb_post.jpg"
# Twitter post (1200×675)
magick "$img" -resize 1200x675^ -gravity center -extent 1200x675 "${base}_tw_post.jpg"
done
Email Newsletter Images
# Optimize images for email
mogrify -path ./email \
-resize 600x\> \
-quality 75 \
-strip \
-interlace Plane \
*.jpg
Backup and Archive
# Create web versions and keep originals
mkdir -p {originals,web}
# Move originals
mv *.jpg originals/
# Create optimized copies
for img in originals/*.jpg; do
base=$(basename "$img")
magick "$img" -resize 2000x2000\> -quality 85 -strip "web/$base"
done